public SevenZipFileInfo(IDirectoryInfo parentDir, string sevenZipPath, uint fileIndex, FileItem fileItem) { _parentDir = parentDir; _sevenZipPath = sevenZipPath; _fileIndex = fileIndex; _fileItem = fileItem; _fullPath = fileItem.Name.Replace("\0", ""); _size = (long)fileItem.Size; }
public static byte[] GetBytes(string sevenZipPath, FileItem fileItem) { lock (_readLock) { //Create temporary directory string tempDir = SysPath.Combine(Environment.CurrentDirectory, "Temp"); if (!Directory.Exists(tempDir)) Directory.CreateDirectory(tempDir); //TODO Will create problems if file name from two different archive are the same //Return file if already extracted string tempFile = SysPath.Combine(tempDir, fileItem.Name.Replace("\0", "")); if (File.Exists(tempFile)) return File.ReadAllBytes(tempFile); //Extract file using (FileStream inStream = File.OpenRead(sevenZipPath)) { ArchiveDatabaseEx archivedatabaseex; new SzIn().szArchiveOpen(inStream, out archivedatabaseex); uint fileIndex = 0; foreach (FileItem item in archivedatabaseex.Database.Files) { if (item.Name.Equals(fileItem.Name)) break; fileIndex = fileIndex + 1; } if (fileIndex == archivedatabaseex.Database.Files.Length) throw new Exception("File is not found within files list"); uint folderIndex = archivedatabaseex.FileIndexToFolderIndexMap[fileIndex]; Dictionary<string, byte[]> outDict = SzExtract.ExtractFolder(inStream, archivedatabaseex, folderIndex); foreach (string fileName in outDict.Keys) { string outPath = SysPath.Combine(tempDir, fileName); string dirPath = SysPath.GetDirectoryName(outPath); if (!Directory.Exists(dirPath)) Directory.CreateDirectory(dirPath); File.WriteAllBytes(outPath, outDict[fileName]); } } return File.ReadAllBytes(tempFile); } }
void SzReadHeader2(SzData sd, ArchiveDatabaseEx db, out ulong[] unPackSizes, out bool[] digestsDefined, out uint[] digests, out bool[] emptyStreamVector, out bool[] emptyFileVector) { // Console.WriteLine("SzReadHeader2 >>>"); EIdEnum type; uint numUnPackStreams = 0; uint numFiles = 0; FileItem[] files = null; uint numEmptyStreams = 0; unPackSizes = null; digestsDefined = null; digests = null; emptyStreamVector = null; emptyFileVector = null; type = szReadID(sd); //Console.WriteLine("SzReadHeader2, got type: " + type); if (type == EIdEnum.k7zIdArchiveProperties) { //SzReadArchiveProperties( sd ); throw new Exception("Need to write szReadArchiveProperties, please contact 7zip port developer"); //type = szReadID(sd); } if (type == EIdEnum.k7zIdMainStreamsInfo) { szReadStreamsInfo(sd, out db.ArchiveInfo.DataStartPosition, db.Database, out numUnPackStreams, out unPackSizes, out digestsDefined, out digests); db.ArchiveInfo.DataStartPosition += db.ArchiveInfo.StartPositionAfterHeader; type = szReadID(sd); } if (type == EIdEnum.k7zIdEnd) { return; } if (type != EIdEnum.k7zIdFilesInfo) { throw new Exception("Error, unexpected type: " + type); } numFiles = szReadNumber32(sd); //Console.WriteLine("SzReadHeader2 Number files: " + numFiles); db.Database.NumFiles = numFiles; files = new FileItem[numFiles]; //RINOK(MySzInAlloc((void **)&files, (size_t)numFiles * sizeof(CFileItem), allocMain->Alloc)); db.Database.Files = files; for (uint i = 0; i < numFiles; i++) { db.Database.Files[i] = new FileItem(); // SzFileInit(files + i); } while (true) { ulong size; type = szReadID(sd); // note to self: maybe need to read type as UInt64??? if (type == EIdEnum.k7zIdEnd) { break; } size = szReadNumber(sd); if ((UInt64)((int)type) != (UInt64)type) // note to self: maybe need to read type as UInt64??? { szSkeepDataSize(sd, size); } else { switch (type) { case EIdEnum.k7zIdName: { szReadSwitch(sd); szReadFileNames(sd, numFiles, files); //RINOK(SzReadFileNames(sd, numFiles, files, allocMain->Alloc)) break; } case EIdEnum.k7zIdEmptyStream: { emptyStreamVector = szReadBoolVector(sd, numFiles); //RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp->Alloc)); numEmptyStreams = 0; for (uint i = 0; i < numFiles; i++) if (emptyStreamVector[i]) numEmptyStreams++; break; } case EIdEnum.k7zIdEmptyFile: { emptyFileVector = szReadBoolVector(sd, numEmptyStreams); //RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp->Alloc)); break; } default: { szSkeepDataSize(sd, size); // RINOK(SzSkeepDataSize(sd, size)); break; } } } uint emptyFileIndex = 0; uint sizeIndex = 0; for (uint i = 0; i < numFiles; i++) { FileItem file = files[i]; file.IsAnti = false; if (emptyStreamVector == null) { file.HasStream = true; } else { file.HasStream = !emptyStreamVector[i]; //file.HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); } if (file.HasStream) { file.IsDirectory = false; file.Size = unPackSizes[sizeIndex]; file.FileCRC = digests[sizeIndex]; file.IsFileCRCDefined = digestsDefined[sizeIndex]; sizeIndex++; } else { if (emptyFileVector == null) { file.IsDirectory = true; } else { file.IsDirectory = !emptyFileVector[emptyFileIndex]; //file.IsDirectory = (Byte)((*emptyFileVector)[emptyFileIndex] ? false : true); } emptyFileIndex++; file.Size = 0; file.IsFileCRCDefined = false; } } } db.Fill(); //foreach (FileItem file in files) //{ // Console.WriteLine(file); //} //Console.WriteLine("SzReadHeader <<<"); }
void szReadFileNames(SzData sd, uint numFiles, FileItem[] files) { //Console.WriteLine("szReadFileNames >>> numfiles: " + numFiles); uint i; for (i = 0; i < numFiles; i++) { uint len = 0; ulong pos = sd.Offset; FileItem file = files[i]; while (pos + 2 <= sd.Length ) { int numAdds; uint value = (uint)(sd.Data[ pos] | (((uint)sd.Data[ pos + 1]) << 8)); pos += 2; len++; if (value == 0) break; if (value < 0x80) continue; if (value >= 0xD800 && value < 0xE000) { uint c2; if (value >= 0xDC00) { throw new Exception("Unexpected value in szReadFileNames: " + value); //return SZE_ARCHIVE_ERROR; } if (pos + 2 > sd.Length ) { throw new Exception("End of file error in szReadFileNames"); //return SZE_ARCHIVE_ERROR; } c2 = (uint)(sd.Data[pos ] | (((uint)sd.Data[pos + 1]) << 8)); pos += 2; if (c2 < 0xDC00 || c2 >= 0xE000) { throw new Exception("Unexpected c2 value in szReadFileNames: " + c2); //return SZE_ARCHIVE_ERROR; } value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((uint)1) << (numAdds * 5 + 6))) break; len += (uint)numAdds; } char[] namechararray = new char[len]; //RINOK(MySzInAlloc((void **)&file->Name, (size_t)len * sizeof(char), allocFunc)); len = 0; while ( sd.Length - sd.Offset >= 2 ) { int numAdds; uint value = (uint)(sd.Data[sd.Offset] | (((uint)sd.Data[sd.Offset + 1]) << 8)); szSkeepDataSize(sd, 2); if (value < 0x80) { namechararray[len++] = (char)value; if (value == 0) break; continue; } if (value >= 0xD800 && value < 0xE000) { uint c2 = (uint)(sd.Data[sd.Offset] | (((uint)sd.Data[sd.Offset + 1]) << 8)); szSkeepDataSize(sd, 2); value = ((value - 0xD800) << 10) | (c2 - 0xDC00); } for (numAdds = 1; numAdds < 5; numAdds++) if (value < (((uint)1) << (numAdds * 5 + 6))) break; namechararray[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); do { numAdds--; namechararray[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); } while (numAdds > 0); len += (uint)numAdds; } file.Name = new String( namechararray ); //Console.WriteLine("Filename: " + file.Name); } }