private ArchivedFile.Builder AddFile(List <ArchivedItem.Builder> items, string fullName, string name) { RemoveItem(items, name); var file = new ArchivedFile.Builder(); file.FullName = fullName; file.Name = name; items.Add(file); mFiles.Add(file); return(file); }
private void RemoveItem(ArchivedFile.Builder file) { mFiles.Remove(file); }
public ArchiveFileModel ReadMetadata(Stream stream, PasswordStorage password) { if (mIsRunning) { throw new InvalidOperationException("Recursive invocation."); } try { mIsRunning = true; // reset fields to detect bugs mFileNames = null; mItemsWithoutStreamMarkers = null; mEmptyFileMarkers = null; mDeletionMarkers = null; mOffsets = null; mAttributes = null; mCDates = null; mMDates = null; mADates = null; mItemCount = -1; mItemsWithoutStream = -1; var metadata = ReadMetadataCore(stream, password); mRootFolder = new ArchivedFolder.Builder(); mItemMap = new Dictionary <ArchivedFolder.Builder, List <ArchivedItem.Builder> >(); mItemMap.Add(mRootFolder, new List <ArchivedItem.Builder>()); mFiles = new HashSet <ArchivedFile.Builder>(); mStreamMap = new List <ArchivedFile.Builder>(); mSectionMap = ImmutableArray.CreateBuilder <int>(metadata.DecoderSections.Length + 1); ArchiveDecoderSection currentDecoder = null; int currentSectionIndex = -1; int currentStreamIndex = 0; int currentStreamCount = 0; int currentEmptyIndex = 0; for (int currentFileIndex = 0; currentFileIndex < mFileNames.Count; currentFileIndex++) { var filename = mFileNames[currentFileIndex]; bool hasStream = false; ArchivedFile.Builder file = null; if (mItemsWithoutStreamMarkers != null && mItemsWithoutStreamMarkers[currentFileIndex]) { var isFile = (mEmptyFileMarkers == null || mEmptyFileMarkers[currentEmptyIndex]); var isDeletionMarker = (mDeletionMarkers != null && mDeletionMarkers[currentEmptyIndex]); if (isDeletionMarker) { RemoveItem(mItemMap[mRootFolder], filename, 0); } else { file = AddItem(mItemMap[mRootFolder], filename, 0, isFile); } currentEmptyIndex++; } else { hasStream = true; file = AddItem(mItemMap[mRootFolder], filename, 0, true); } if (file != null) { if (mOffsets != null) { file.Offset = mOffsets[currentFileIndex] ?? 0; } if (mAttributes != null) { var attr = mAttributes[currentFileIndex]; if (attr.HasValue && (attr.Value & ArchivedAttributesExtensions.DirectoryAttribute) != 0) { continue; } file.Attributes = attr; } if (mCDates != null) { file.Creation = mCDates[currentFileIndex]; } if (mMDates != null) { file.LastWrite = mMDates[currentFileIndex]; } if (mADates != null) { file.LastAccess = mADates[currentFileIndex]; } if (hasStream) { while (currentStreamIndex == currentStreamCount) { if (currentSectionIndex == metadata.DecoderSections.Length - 1) { throw new InvalidDataException(); } currentDecoder = metadata.DecoderSections[++currentSectionIndex]; currentStreamCount = currentDecoder.Streams.Length; currentStreamIndex = 0; mSectionMap.Add(mStreamMap.Count); } file.Stream = new DecodedStreamIndex(currentSectionIndex, currentStreamIndex); var streamMetadata = currentDecoder.Streams[currentStreamIndex++]; file.Length = streamMetadata.Length; file.Checksum = streamMetadata.Checksum; } } if (hasStream) { mStreamMap.Add(file); } } var finalStreamMap = ImmutableList.CreateBuilder <ArchivedFile>(); foreach (var file in mStreamMap) { finalStreamMap.Add(mFiles.Contains(file) ? file.ToImmutable() : null); } if (currentStreamIndex != currentStreamCount || currentSectionIndex != metadata.DecoderSections.Length - 1) { throw new InvalidDataException(); } mSectionMap.Add(finalStreamMap.Count); return(new ArchiveFileModel(metadata, BuildFolder(mRootFolder), mSectionMap.MoveToImmutable(), finalStreamMap.ToImmutable())); } finally { mIsRunning = false; } }