aboutsummaryrefslogtreecommitdiff
path: root/CPP/7zip/Archive/ZHandler.cpp
blob: 18e712ac8dd2b07d29a51f41e9ab27b562e600e5 (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
// ZHandler.cpp

#include "StdAfx.h"

#include "../../Common/ComTry.h"

#include "../../Windows/PropVariant.h"

#include "../Common/ProgressUtils.h"
#include "../Common/RegisterArc.h"
#include "../Common/StreamUtils.h"

#include "../Compress/ZDecoder.h"

#include "Common/DummyOutStream.h"

namespace NArchive {
namespace NZ {

Z7_CLASS_IMP_CHandler_IInArchive_0

  CMyComPtr<IInStream> _stream;
  UInt64 _packSize;
  // UInt64 _unpackSize;
  // bool _unpackSize_Defined;
};

static const Byte kProps[] =
{
  kpidPackSize
};

IMP_IInArchive_Props
IMP_IInArchive_ArcProps_NO_Table

Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
{
  *numItems = 1;
  return S_OK;
}

Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
{
  NWindows::NCOM::CPropVariant prop;
  switch (propID)
  {
    case kpidPhySizeCantBeDetected: prop = true; break;
  }
  prop.Detach(value);
  return S_OK;
}

Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))
{
  NWindows::NCOM::CPropVariant prop;
  switch (propID)
  {
    // case kpidSize: if (_unpackSize_Defined) prop = _unpackSize; break;
    case kpidPackSize: prop = _packSize; break;
  }
  prop.Detach(value);
  return S_OK;
}

/*
Z7_CLASS_IMP_COM_1(
  CCompressProgressInfoImp
  , ICompressProgressInfo
)
  CMyComPtr<IArchiveOpenCallback> Callback;
public:
  void Init(IArchiveOpenCallback *callback) { Callback = callback; }
};

Z7_COM7F_IMF(CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize))
{
  outSize = outSize;
  if (Callback)
  {
    const UInt64 files = 1;
    return Callback->SetCompleted(&files, inSize);
  }
  return S_OK;
}
*/

API_FUNC_static_IsArc IsArc_Z(const Byte *p, size_t size)
{
  if (size < 3)
    return k_IsArc_Res_NEED_MORE;
  if (size > NCompress::NZ::kRecommendedCheckSize)
    size = NCompress::NZ::kRecommendedCheckSize;
  if (!NCompress::NZ::CheckStream(p, size))
    return k_IsArc_Res_NO;
  return k_IsArc_Res_YES;
}
}

Z7_COM7F_IMF(CHandler::Open(IInStream *stream,
    const UInt64 * /* maxCheckStartPosition */,
    IArchiveOpenCallback * /* openCallback */))
{
  COM_TRY_BEGIN
  {
    // RINOK(InStream_GetPos(stream, _streamStartPosition));
    Byte buffer[NCompress::NZ::kRecommendedCheckSize];
    // Byte buffer[1500];
    size_t size = NCompress::NZ::kRecommendedCheckSize;
    // size = 700;
    RINOK(ReadStream(stream, buffer, &size))
    if (!NCompress::NZ::CheckStream(buffer, size))
      return S_FALSE;

    UInt64 endPos;
    RINOK(InStream_GetSize_SeekToEnd(stream, endPos))
    _packSize = endPos;
  
    /*
    bool fullCheck = false;
    if (fullCheck)
    {
      CCompressProgressInfoImp *compressProgressSpec = new CCompressProgressInfoImp;
      CMyComPtr<ICompressProgressInfo> compressProgress = compressProgressSpec;
      compressProgressSpec->Init(openCallback);

      NCompress::NZ::CDecoder *decoderSpec = new NCompress::NZ::CDecoder;
      CMyComPtr<ICompressCoder> decoder = decoderSpec;

      CDummyOutStream *outStreamSpec = new CDummyOutStream;
      CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
      outStreamSpec->SetStream(NULL);
      outStreamSpec->Init();
      decoderSpec->SetProp(_prop);
      if (openCallback)
      {
        UInt64 files = 1;
        RINOK(openCallback->SetTotal(&files, &endPos));
      }
      RINOK(InStream_SeekSet(stream, _streamStartPosition + kSignatureSize))
      HRESULT res = decoder->Code(stream, outStream, NULL, NULL, openCallback ? compressProgress : NULL);
      if (res != S_OK)
        return S_FALSE;
      _packSize = decoderSpec->PackSize;
    }
    */
    _stream = stream;
  }
  return S_OK;
  COM_TRY_END
}

Z7_COM7F_IMF(CHandler::Close())
{
  _packSize = 0;
  // _unpackSize_Defined = false;
  _stream.Release();
  return S_OK;
}


Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
    Int32 testMode, IArchiveExtractCallback *extractCallback))
{
  COM_TRY_BEGIN
  if (numItems == 0)
    return S_OK;
  if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
    return E_INVALIDARG;

  extractCallback->SetTotal(_packSize);

  UInt64 currentTotalPacked = 0;
  
  RINOK(extractCallback->SetCompleted(&currentTotalPacked))
  
  CMyComPtr<ISequentialOutStream> realOutStream;
  const Int32 askMode = testMode ?
      NExtract::NAskMode::kTest :
      NExtract::NAskMode::kExtract;
  
  RINOK(extractCallback->GetStream(0, &realOutStream, askMode))
    
  if (!testMode && !realOutStream)
    return S_OK;

  extractCallback->PrepareOperation(askMode);

  CDummyOutStream *outStreamSpec = new CDummyOutStream;
  CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
  outStreamSpec->SetStream(realOutStream);
  outStreamSpec->Init();
  realOutStream.Release();

  CLocalProgress *lps = new CLocalProgress;
  CMyComPtr<ICompressProgressInfo> progress = lps;
  lps->Init(extractCallback, true);
  
  RINOK(InStream_SeekToBegin(_stream))

  NCompress::NZ::CDecoder *decoderSpec = new NCompress::NZ::CDecoder;
  CMyComPtr<ICompressCoder> decoder = decoderSpec;

  int opRes;
  {
    HRESULT result = decoder->Code(_stream, outStream, NULL, NULL, progress);
    if (result == S_FALSE)
      opRes = NExtract::NOperationResult::kDataError;
    else
    {
      RINOK(result)
      opRes = NExtract::NOperationResult::kOK;
    }
  }
  // _unpackSize = outStreamSpec->GetSize();
  // _unpackSize_Defined = true;
  outStream.Release();
  return extractCallback->SetOperationResult(opRes);
  COM_TRY_END
}

static const Byte k_Signature[] = { 0x1F, 0x9D };

REGISTER_ARC_I(
  "Z", "z taz", "* .tar", 5,
  k_Signature,
  0,
  0,
  IsArc_Z)

}}