Esempio n. 1
0
	ssize_t ArchiveExtract::execute()
	{
		LogTrace();
		Com::Object<IArchiveExtractCallback> extractCallback(new ExtractCallback(m_archive, m_dest));
		CheckCom(m_archive->Extract(nullptr, (UInt32 )-1, false, extractCallback));
		return 0;
	}
Esempio n. 2
0
	ssize_t ArchiveTest::execute()
	{
		LogTrace();
		ExtractCallback * callback(new ExtractCallback(m_archive));
		LogTrace();
		Com::Object<IArchiveExtractCallback> extractCallback(callback);
		LogTrace();
		m_archive->Extract(nullptr, (UInt32)-1, true, extractCallback);
		LogTrace();
		return static_cast<ssize_t>(callback->failed_files.size());
	}
Esempio n. 3
0
HRESULT CZipDecoder::Decode(
    CInArchive &archive, const CItemEx &item,
    ISequentialOutStream *realOutStream,
    IArchiveExtractCallback *_extractCallback,
    quint32 numThreads, qint32 &res)
{
    RefPtr<IArchiveExtractCallback> extractCallback(_extractCallback);

    res = NArchive::NExtract::NOperationResult::kDataError;
    CInStreamReleaser inStreamReleaser;

    bool needCRC = true;
    bool aesMode = false;
#ifdef ZIP_STRONG_SUPORT
    bool pkAesMode = false;
#endif
    quint16 methodId = item.CompressionMethod;
    if (item.IsEncrypted()) {
        if (item.IsStrongEncrypted()) {
#ifdef ZIP_STRONG_SUPORT
            CStrongCryptoField f;
            if (item.CentralExtra.GetStrongCryptoField(f)) {
                pkAesMode = true;
            }
            if (!pkAesMode)
#endif
            {
                res = NArchive::NExtract::NOperationResult::kUnSupportedMethod;
                return S_OK;
            }
        }
        if (methodId == NFileHeader::NCompressionMethod::kWzAES) {
            CWzAesExtraField aesField;
            if (item.CentralExtra.GetWzAesField(aesField)) {
                aesMode = true;
                needCRC = aesField.NeedCrc();
            }
        }
    }

    COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
    RefPtr<ISequentialOutStream> outStream = outStreamSpec;
    outStreamSpec->SetStream(realOutStream);
    outStreamSpec->Init(needCRC);

    quint64 authenticationPos;

    RefPtr<ISequentialInStream> inStream;
    {
        quint64 packSize = item.PackSize;
        if (aesMode) {
            if (packSize < NCrypto::NWzAES::kMacSize)
                return S_OK;
            packSize -= NCrypto::NWzAES::kMacSize;
        }
        quint64 dataPos = item.GetDataPosition();
        inStream = archive.CreateLimitedStream(dataPos, packSize);
        authenticationPos = dataPos + packSize;
    }

    RefPtr<ICompressFilter> cryptoFilter;
    if (item.IsEncrypted()) {
        if (aesMode) {
            CWzAesExtraField aesField;
            if (!item.CentralExtra.GetWzAesField(aesField))
                return S_OK;
            methodId = aesField.Method;
            if (!_aesDecoder) {
                _aesDecoderSpec = new NCrypto::NWzAES::CDecoder;
                _aesDecoder = _aesDecoderSpec;
            }
            cryptoFilter = _aesDecoder;
            quint8 properties = aesField.Strength;
            RINOK(_aesDecoderSpec->SetDecoderProperties2(&properties, 1));
        }
#ifdef ZIP_STRONG_SUPORT
        else if (pkAesMode) {
            if (!_zsDecoder) {
                _zsDecoderSpec = new NCrypto::NZipStrong::CDecoder;
                _zsDecoder = _zsDecoderSpec;
            }
            cryptoFilter = _zsDecoder;
        }
#endif
        else {
            if (!_zipCryptoDecoder) {
                _zipCryptoDecoderSpec = new NCrypto::NZip::CDecoder;
                _zipCryptoDecoder = _zipCryptoDecoderSpec;
            }
            cryptoFilter = _zipCryptoDecoder;
        }
        RefPtr<ICryptoSetPassword> cryptoSetPassword;
        RINOK(cryptoFilter.QueryInterface(&cryptoSetPassword));

        if (!getTextPassword)
            extractCallback.QueryInterface(&getTextPassword);

        if (getTextPassword) {
            QString password;
            RINOK(getTextPassword->CryptoGetTextPassword(&password));
            QByteArray charPassword;
            if (aesMode
#ifdef ZIP_STRONG_SUPORT
                    || pkAesMode
#endif
               ) {
                charPassword = password.toUtf8();
                /*
                for (int i = 0;; i++)
                {
                  wchar_t c = password[i];
                  if (c == 0)
                    break;
                  if (c >= 0x80)
                  {
                    res = NArchive::NExtract::NOperationResult::kDataError;
                    return S_OK;
                  }
                  charPassword += (char)c;
                }
                */
            } else {
                // we use OEM. WinZip/Windows probably use ANSI for some files
                charPassword = password.toLocal8Bit();
            }
            HRESULT res = cryptoSetPassword->CryptoSetPassword(
                              (const quint8 *)charPassword.constData(), charPassword.length());
            if (res != S_OK)
                return S_OK;
        } else {
            RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
        }
    }

    int m;
    for (m = 0; m < methodItems.size(); m++)
        if (methodItems[m]->ZipMethod == methodId)
            break;

    if (m == methodItems.size()) {
        CMethodItem mi;
        mi.ZipMethod = methodId;
        if (methodId == NFileHeader::NCompressionMethod::kStored)
            mi.Coder = new NCompress::CCopyCoder;
        else if (methodId == NFileHeader::NCompressionMethod::kShrunk)
            mi.Coder = new NCompress::NShrink::CDecoder;
        else if (methodId == NFileHeader::NCompressionMethod::kImploded)
            mi.Coder = new NCompress::NImplode::NDecoder::CCoder;
        else {
            CMethodId szMethodID;
            if (methodId == NFileHeader::NCompressionMethod::kBZip2)
                szMethodID = kMethodId_BZip2;
            else {
                if (methodId > 0xFF) {
                    res = NArchive::NExtract::NOperationResult::kUnSupportedMethod;
                    return S_OK;
                }
                szMethodID = kMethodId_ZipBase + (quint8)methodId;
            }

            QObject *dec = CreateDecoderForId(szMethodID);
            if (dec)
                mi.Coder = qobject_cast<ICompressCoder *>(dec);

            if (mi.Coder == 0) {
                delete dec;
                res = NArchive::NExtract::NOperationResult::kUnSupportedMethod;
                return S_OK;
            }
        }
        methodItems.append(new CMethodItem(mi));
        m = methodItems.size() - 1;
    }
    RefPtr<ICompressCoder> coder(methodItems[m]->Coder);

    {
        RefPtr<ICompressSetDecoderProperties2> setDecoderProperties;
        coder.QueryInterface(&setDecoderProperties);
        if (setDecoderProperties) {
            quint8 properties = (quint8)item.Flags;
            RINOK(setDecoderProperties->SetDecoderProperties2(&properties, 1));
        }
    }

#ifdef THREADED
    {
        RefPtr<ICompressSetCoderMt> setCoderMt;
        coder.QueryInterface(&setCoderMt);
        if (setCoderMt) {
            RINOK(setCoderMt->SetNumberOfThreads(numThreads));
        }
    }
#endif
    {
        HRESULT result;
        RefPtr<ISequentialInStream> inStreamNew;
        if (item.IsEncrypted()) {
            if (!filterStream) {
                filterStreamSpec = new CFilterCoder;
                filterStream = filterStreamSpec;
            }
            filterStreamSpec->setFilter(cryptoFilter);
            if (aesMode) {
                RINOK(_aesDecoderSpec->ReadHeader(inStream));
            }
#ifdef ZIP_STRONG_SUPORT
            else if (pkAesMode) {
                RINOK(_zsDecoderSpec->ReadHeader(inStream));
            }
#endif
            else {
                RINOK(_zipCryptoDecoderSpec->ReadHeader(inStream));
            }
            RINOK(filterStreamSpec->SetInStream(inStream));
            inStreamReleaser.FilterCoder = filterStreamSpec;
            inStreamNew = filterStream;

            if (aesMode) {
                if (!_aesDecoderSpec->CheckPasswordVerifyCode())
                    return S_OK;
            }
        } else
            inStreamNew = inStream;
        result = coder->Code(inStreamNew, outStream, NULL, &item.UnPackSize);
        if (result == S_FALSE)
            return S_OK;
        RINOK(result);
    }
    bool crcOK = true;
    bool authOk = true;
    if (needCRC)
        crcOK = (outStreamSpec->GetCRC() == item.FileCRC);
    if (aesMode) {
        inStream = archive.CreateLimitedStream(authenticationPos, NCrypto::NWzAES::kMacSize);
        if (_aesDecoderSpec->CheckMac(inStream, authOk) != S_OK)
            authOk = false;
    }

    res = ((crcOK && authOk) ?
           NArchive::NExtract::NOperationResult::kOK :
           NArchive::NExtract::NOperationResult::kCRCError);
    return S_OK;
}