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; }
hlBool CNCFFile::GetFileValidationInternal(const CDirectoryFile *pFile, HLValidation &eValidation) const { if(this->lpRootPath != 0) { hlChar lpTemp[512]; this->GetPath(pFile, lpTemp, sizeof(lpTemp)); hlUInt uiSize; if(HLLib::GetFileSize(lpTemp, uiSize)) { if(uiSize < this->lpDirectoryEntries[pFile->GetID()].uiItemSize) { eValidation = HL_VALIDATES_INCOMPLETE; } else if(this->lpDirectoryEntries[pFile->GetID()].uiDirectoryFlags & HL_NCF_FLAG_ENCRYPTED) { // No way of checking, assume it's ok. eValidation = HL_VALIDATES_ASSUMED_OK; } else if(this->lpDirectoryEntries[pFile->GetID()].uiChecksumIndex == 0xffffffff) { // File has no checksum. eValidation = HL_VALIDATES_ASSUMED_OK; } else { Streams::CFileStream Stream = Streams::CFileStream(lpTemp); if(Stream.Open(HL_MODE_READ)) { eValidation = HL_VALIDATES_OK; hlULongLong uiTotalBytes = 0, uiFileBytes = Stream.GetStreamSize(); hlUInt uiBufferSize; hlByte *lpBuffer = new hlByte[this->pDirectoryHeader->uiChecksumDataLength]; const NCFChecksumMapEntry *pChecksumMapEntry = this->lpChecksumMapEntries + this->lpDirectoryEntries[pFile->GetID()].uiChecksumIndex; hlBool bCancel = hlFalse; hlValidateFileProgress(const_cast<CDirectoryFile *>(pFile), uiTotalBytes, uiFileBytes, &bCancel); hlUInt i = 0; while((uiBufferSize = Stream.Read(lpBuffer, this->pDirectoryHeader->uiChecksumDataLength)) != 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++; } delete []lpBuffer; Stream.Close(); } else { eValidation = HL_VALIDATES_ERROR; } } } else { // Not found. if(this->lpDirectoryEntries[pFile->GetID()].uiItemSize != 0) { eValidation = HL_VALIDATES_INCOMPLETE; } else { eValidation = HL_VALIDATES_OK; } } } else { eValidation = HL_VALIDATES_ASSUMED_OK; } return hlTrue; }