Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/modules/libjar/zipwriter/nsZipDataStream.cpp
Line
Count
Source (jump to first uncovered line)
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
 */
5
6
#include "StreamFunctions.h"
7
#include "nsZipDataStream.h"
8
#include "nsStringStream.h"
9
#include "nsISeekableStream.h"
10
#include "nsDeflateConverter.h"
11
#include "nsNetUtil.h"
12
#include "nsComponentManagerUtils.h"
13
#include "nsMemory.h"
14
15
0
#define ZIP_METHOD_STORE 0
16
0
#define ZIP_METHOD_DEFLATE 8
17
18
using namespace mozilla;
19
20
/**
21
 * nsZipDataStream handles the writing an entry's into the zip file.
22
 * It is set up to wither write the data as is, or in the event that compression
23
 * has been requested to pass it through a stream converter.
24
 * Currently only the deflate compression method is supported.
25
 * The CRC checksum for the entry's data is also generated here.
26
 */
27
NS_IMPL_ISUPPORTS(nsZipDataStream, nsIStreamListener,
28
                  nsIRequestObserver)
29
30
nsresult nsZipDataStream::Init(nsZipWriter *aWriter,
31
                               nsIOutputStream *aStream,
32
                               nsZipHeader *aHeader,
33
                               int32_t aCompression)
34
0
{
35
0
    mWriter = aWriter;
36
0
    mHeader = aHeader;
37
0
    mStream = aStream;
38
0
    mHeader->mCRC = crc32(0L, Z_NULL, 0);
39
0
40
0
    nsresult rv = NS_NewSimpleStreamListener(getter_AddRefs(mOutput), aStream,
41
0
                                             nullptr);
42
0
    NS_ENSURE_SUCCESS(rv, rv);
43
0
44
0
    if (aCompression > 0) {
45
0
        mHeader->mMethod = ZIP_METHOD_DEFLATE;
46
0
        nsCOMPtr<nsIStreamConverter> converter =
47
0
                              new nsDeflateConverter(aCompression);
48
0
        NS_ENSURE_TRUE(converter, NS_ERROR_OUT_OF_MEMORY);
49
0
50
0
        rv = converter->AsyncConvertData("uncompressed", "rawdeflate", mOutput,
51
0
                                         nullptr);
52
0
        NS_ENSURE_SUCCESS(rv, rv);
53
0
54
0
        mOutput = do_QueryInterface(converter, &rv);
55
0
        NS_ENSURE_SUCCESS(rv, rv);
56
0
    }
57
0
    else {
58
0
        mHeader->mMethod = ZIP_METHOD_STORE;
59
0
    }
60
0
61
0
    return NS_OK;
62
0
}
63
64
NS_IMETHODIMP nsZipDataStream::OnDataAvailable(nsIRequest *aRequest,
65
                                               nsISupports *aContext,
66
                                               nsIInputStream *aInputStream,
67
                                               uint64_t aOffset,
68
                                               uint32_t aCount)
69
0
{
70
0
    if (!mOutput)
71
0
        return NS_ERROR_NOT_INITIALIZED;
72
0
73
0
    auto buffer = MakeUnique<char[]>(aCount);
74
0
    NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
75
0
76
0
    nsresult rv = ZW_ReadData(aInputStream, buffer.get(), aCount);
77
0
    NS_ENSURE_SUCCESS(rv, rv);
78
0
79
0
    return ProcessData(aRequest, aContext, buffer.get(), aOffset, aCount);
80
0
}
81
82
NS_IMETHODIMP nsZipDataStream::OnStartRequest(nsIRequest *aRequest,
83
                                              nsISupports *aContext)
84
0
{
85
0
    if (!mOutput)
86
0
        return NS_ERROR_NOT_INITIALIZED;
87
0
88
0
    return mOutput->OnStartRequest(aRequest, aContext);
89
0
}
90
91
NS_IMETHODIMP nsZipDataStream::OnStopRequest(nsIRequest *aRequest,
92
                                             nsISupports *aContext,
93
                                             nsresult aStatusCode)
94
0
{
95
0
    if (!mOutput)
96
0
        return NS_ERROR_NOT_INITIALIZED;
97
0
98
0
    nsresult rv = mOutput->OnStopRequest(aRequest, aContext, aStatusCode);
99
0
    mOutput = nullptr;
100
0
    if (NS_FAILED(rv)) {
101
0
        mWriter->EntryCompleteCallback(mHeader, rv);
102
0
    }
103
0
    else {
104
0
        rv = CompleteEntry();
105
0
        rv = mWriter->EntryCompleteCallback(mHeader, rv);
106
0
    }
107
0
108
0
    mStream = nullptr;
109
0
    mWriter = nullptr;
110
0
    mHeader = nullptr;
111
0
112
0
    return rv;
113
0
}
114
115
inline nsresult nsZipDataStream::CompleteEntry()
116
0
{
117
0
    nsresult rv;
118
0
    nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mStream, &rv);
119
0
    NS_ENSURE_SUCCESS(rv, rv);
120
0
    int64_t pos;
121
0
    rv = seekable->Tell(&pos);
122
0
    NS_ENSURE_SUCCESS(rv, rv);
123
0
124
0
    mHeader->mCSize = pos - mHeader->mOffset - mHeader->GetFileHeaderLength();
125
0
    mHeader->mWriteOnClose = true;
126
0
    return NS_OK;
127
0
}
128
129
nsresult nsZipDataStream::ProcessData(nsIRequest *aRequest,
130
                                      nsISupports *aContext, char *aBuffer,
131
                                      uint64_t aOffset, uint32_t aCount)
132
0
{
133
0
    mHeader->mCRC = crc32(mHeader->mCRC,
134
0
                          reinterpret_cast<const unsigned char*>(aBuffer),
135
0
                          aCount);
136
0
137
0
    MOZ_ASSERT(aCount <= INT32_MAX);
138
0
    nsCOMPtr<nsIInputStream> stream;
139
0
    nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
140
0
          aBuffer, aCount);
141
0
    NS_ENSURE_SUCCESS(rv, rv);
142
0
143
0
    rv = mOutput->OnDataAvailable(aRequest, aContext, stream, aOffset, aCount);
144
0
    mHeader->mUSize += aCount;
145
0
146
0
    return rv;
147
0
}
148
149
nsresult nsZipDataStream::ReadStream(nsIInputStream *aStream)
150
0
{
151
0
    if (!mOutput)
152
0
        return NS_ERROR_NOT_INITIALIZED;
153
0
154
0
    nsresult rv = OnStartRequest(nullptr, nullptr);
155
0
    NS_ENSURE_SUCCESS(rv, rv);
156
0
157
0
    auto buffer = MakeUnique<char[]>(4096);
158
0
    NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
159
0
160
0
    uint32_t read = 0;
161
0
    uint32_t offset = 0;
162
0
    do
163
0
    {
164
0
        rv = aStream->Read(buffer.get(), 4096, &read);
165
0
        if (NS_FAILED(rv)) {
166
0
            OnStopRequest(nullptr, nullptr, rv);
167
0
            return rv;
168
0
        }
169
0
170
0
        if (read > 0) {
171
0
            rv = ProcessData(nullptr, nullptr, buffer.get(), offset, read);
172
0
            if (NS_FAILED(rv)) {
173
0
                OnStopRequest(nullptr, nullptr, rv);
174
0
                return rv;
175
0
            }
176
0
            offset += read;
177
0
        }
178
0
    } while (read > 0);
179
0
180
0
    return OnStopRequest(nullptr, nullptr, NS_OK);
181
0
}