hlBool CDirectoryFile::Extract(const hlChar *lpPath) const
{
	hlExtractItemStart(this);

	hlChar *lpName = new hlChar[strlen(this->GetName()) + 1];
	strcpy(lpName, this->GetName());
	RemoveIllegalCharacters(lpName);

	hlChar *lpFileName;
	if(lpPath == 0 || *lpPath == '\0')
	{
		lpFileName = new hlChar[strlen(lpName) + 1];
		strcpy(lpFileName, lpName);
	}
	else
	{
		lpFileName = new hlChar[strlen(lpPath) + 1 + strlen(lpName) + 1];
		strcpy(lpFileName, lpPath);
		strcat(lpFileName, PATH_SEPARATOR_STRING);
		strcat(lpFileName, lpName);
	}

	FixupIllegalCharacters(lpFileName);

	hlBool bResult;
	if(!bOverwriteFiles && GetFileExists(lpFileName))
	{
		bResult = hlTrue;
	}
	else
	{
		bResult = hlFalse;

		Streams::IStream *pInput = 0;

		if(this->GetPackage()->CreateStream(this, pInput))
		{
			if(pInput->Open(HL_MODE_READ))
			{
				Streams::CFileStream Output = Streams::CFileStream(lpFileName);

				if(Output.Open(HL_MODE_WRITE | HL_MODE_CREATE))
				{
					hlUInt uiTotalBytes = 0, uiFileBytes = this->GetSize();
					hlByte lpBuffer[HL_DEFAULT_COPY_BUFFER_SIZE];

					hlBool bCancel = hlFalse;
					hlExtractFileProgress(this, uiTotalBytes, uiFileBytes, &bCancel);

					while(hlTrue)
					{
						if(bCancel)
						{
							LastError.SetErrorMessage("Canceled by user.");
						}

						hlUInt uiBytes = pInput->Read(lpBuffer, sizeof(lpBuffer));

						if(uiBytes == 0)
						{
							bResult = uiTotalBytes == pInput->GetStreamSize();
							break;
						}

						if(Output.Write(lpBuffer, uiBytes) != uiBytes)
						{
							break;
						}

						uiTotalBytes += uiBytes;

						hlExtractFileProgress(this, uiTotalBytes, uiFileBytes, &bCancel);
					}

					Output.Close();
				}

				pInput->Close();
			}

			this->GetPackage()->ReleaseStream(pInput);
		}
	}

	delete []lpFileName;
	delete []lpName;

	hlExtractItemEnd(this, bResult);

	return bResult;
}
Beispiel #2
0
hlBool CVPKFile::GetFileValidationInternal(const CDirectoryFile *pFile, HLValidation &eValidation) const
{
	hlBool bExtractable = hlFalse;
	if(GetFileExtractableInternal(pFile, bExtractable))
	{
		if(bExtractable)
		{
			Streams::IStream *pStream = 0;
			if(this->CreateStreamInternal(pFile, pStream))
			{
				if(pStream->Open(HL_MODE_READ))
				{
					hlULong uiChecksum = 0;
					eValidation = HL_VALIDATES_OK;

					hlULongLong uiTotalBytes = 0, uiFileBytes = pStream->GetStreamSize();
					hlUInt uiBufferSize;
					hlByte lpBuffer[HL_VPK_CHECKSUM_LENGTH];

					hlBool bCancel = hlFalse;
					hlValidateFileProgress(const_cast<CDirectoryFile *>(pFile), uiTotalBytes, uiFileBytes, &bCancel);

					while((uiBufferSize = pStream->Read(lpBuffer, HL_VPK_CHECKSUM_LENGTH)) != 0)
					{
						if(bCancel)
						{
							// User canceled.
							eValidation = HL_VALIDATES_CANCELED;
							break;
						}

						uiChecksum = CRC32(lpBuffer, uiBufferSize, uiChecksum);

						uiTotalBytes += static_cast<hlULongLong>(uiBufferSize);

						hlValidateFileProgress(const_cast<CDirectoryFile *>(pFile), uiTotalBytes, uiFileBytes, &bCancel);
					}

					if(!bCancel)
					{
						const VPKDirectoryItem *pDirectoryItem = static_cast<const VPKDirectoryItem *>(pFile->GetData());
						if(pDirectoryItem->pDirectoryEntry->uiCRC != uiChecksum)
						{
							eValidation = HL_VALIDATES_CORRUPT;
						}
					}

					pStream->Close();
				}
				else
				{
					eValidation = HL_VALIDATES_ERROR;
				}

				this->ReleaseStreamInternal(*pStream);
				delete pStream;
			}
			else
			{
				eValidation = HL_VALIDATES_ERROR;
			}
		}
		else
		{
			eValidation = HL_VALIDATES_INCOMPLETE;
		}
	}
	else
	{
		eValidation = HL_VALIDATES_ERROR;
	}

	return hlTrue;
}
Beispiel #3
0
hlBool CGCFFile::GetFileValidationInternal(const CDirectoryFile *pFile, HLValidation &eValidation) const
{
    // Do we have enough data to validate?
    {
        hlUInt uiSize = 0;

        // Get the first data block.
        hlUInt uiBlockEntryIndex = this->lpDirectoryMapEntries[pFile->GetID()].uiFirstBlockIndex;

        // Loop through each data block.
        while(uiBlockEntryIndex != this->pDataBlockHeader->uiBlockCount)
        {
            uiSize += this->lpBlockEntries[uiBlockEntryIndex].uiFileDataSize;

            // Get the next data block.
            uiBlockEntryIndex = this->lpBlockEntries[uiBlockEntryIndex].uiNextBlockEntryIndex;
        }

        if(uiSize != this->lpDirectoryEntries[pFile->GetID()].uiItemSize)
        {
            // File is incomplete.
            eValidation = HL_VALIDATES_INCOMPLETE;
            return hlTrue;
        }
    }

    if((this->lpDirectoryEntries[pFile->GetID()].uiDirectoryFlags & HL_GCF_FLAG_ENCRYPTED) != 0)
    {
        // No way of checking, assume it's ok.
        eValidation = HL_VALIDATES_ASSUMED_OK;
        return hlTrue;
    }

    // File has no checksum.
    if(this->lpDirectoryEntries[pFile->GetID()].uiChecksumIndex == 0xffffffff)
    {
        eValidation = HL_VALIDATES_ASSUMED_OK;
        return hlTrue;
    }

    Streams::IStream *pStream = 0;
    if(this->CreateStreamInternal(pFile, pStream))
    {
        if(pStream->Open(HL_MODE_READ))
        {
            eValidation = HL_VALIDATES_OK;

            hlULongLong uiTotalBytes = 0, uiFileBytes = pStream->GetStreamSize();
            hlUInt uiBufferSize;
            hlByte lpBuffer[HL_GCF_CHECKSUM_LENGTH];

            const GCFChecksumMapEntry *pChecksumMapEntry = this->lpChecksumMapEntries + this->lpDirectoryEntries[pFile->GetID()].uiChecksumIndex;

            hlBool bCancel = hlFalse;
            hlValidateFileProgress(const_cast<CDirectoryFile *>(pFile), uiTotalBytes, uiFileBytes, &bCancel);

            hlUInt i = 0;
            while((uiBufferSize = pStream->Read(lpBuffer, HL_GCF_CHECKSUM_LENGTH)) != 0)
            {
                if(bCancel)
                {
                    // User canceled.
                    eValidation = HL_VALIDATES_CANCELED;
                    break;
                }

                if(i >= pChecksumMapEntry->uiChecksumCount)
                {
                    // Something bad happened.
                    eValidation = HL_VALIDATES_ERROR;
                    break;
                }

                hlULong uiChecksum = Adler32(lpBuffer, uiBufferSize) ^ CRC32(lpBuffer, uiBufferSize);
                if(uiChecksum != this->lpChecksumEntries[pChecksumMapEntry->uiFirstChecksumIndex + i].uiChecksum)
                {
                    eValidation = HL_VALIDATES_CORRUPT;
                    break;
                }

                uiTotalBytes += static_cast<hlULongLong>(uiBufferSize);

                hlValidateFileProgress(const_cast<CDirectoryFile *>(pFile), uiTotalBytes, uiFileBytes, &bCancel);

                i++;
            }

            pStream->Close();
        }
        else
        {
            eValidation = HL_VALIDATES_ERROR;
        }

        this->ReleaseStreamInternal(*pStream);
        delete pStream;
    }
    else
    {
        eValidation = HL_VALIDATES_ERROR;
    }

    return hlTrue;
}