示例#1
0
        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);
        }
示例#2
0
 private void RemoveItem(ArchivedFile.Builder file)
 {
     mFiles.Remove(file);
 }
示例#3
0
        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;
            }
        }