Exemple #1
0
        private static void findPrimaryOutStreamIndex(SevenZipHeader.Folder folder, out UInt64 primaryCoderIndex, out UInt64 primaryOutStreamIndex)
        {
            bool foundPrimaryOutStream = false;

            primaryCoderIndex     = 0;
            primaryOutStreamIndex = 0;

            for (UInt64 outStreamIndex = 0, coderIndex = 0;
                 coderIndex < (UInt64)folder.CodersInfo.LongLength;
                 coderIndex++)
            {
                for (UInt64 coderOutStreamIndex = 0;
                     coderOutStreamIndex < folder.CodersInfo[coderIndex].NumOutStreams;
                     coderOutStreamIndex++, outStreamIndex++)
                {
                    if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
                    {
                        if (foundPrimaryOutStream)
                        {
                            throw new SevenZipException("Multiple output streams are not supported.");
                        }

                        foundPrimaryOutStream = true;
                        primaryCoderIndex     = coderIndex;
                        primaryOutStreamIndex = outStreamIndex;
                    }
                }
            }

            if (!foundPrimaryOutStream)
            {
                throw new SevenZipException("No primary output stream in folder.");
            }
        }
Exemple #2
0
 private static UInt64 findCoderIndexForOutStreamIndex(SevenZipHeader.Folder folder, UInt64 outStreamIndex)
 {
     for (ulong coderIndex = 0, index = 0; coderIndex < folder.NumCoders; ++coderIndex)
     {
         for (ulong i = 0; i < folder.CodersInfo[coderIndex].NumOutStreams; ++i, ++index)
         {
             if (outStreamIndex == index)
             {
                 return(coderIndex);
             }
         }
     }
     throw new SevenZipException($"Could not find coder index for out stream index `{outStreamIndex}`.");
 }
Exemple #3
0
        private Stream createDecoderStream(ulong folderIndex, ulong packIndex)
        {
            // find initial position of packed streams
            ulong packPos = streamsInfo.PackInfo.PackPos + (ulong)Marshal.SizeOf(typeof(SevenZipArchive.SignatureHeader));

            for (ulong i = 0; i < packIndex; ++i)
            {
                packPos += streamsInfo.PackInfo.Sizes[i];
            }

            // catch current folder info
            SevenZipHeader.Folder folder = streamsInfo.UnPackInfo.Folders[folderIndex];

            // create packed substreams
            Stream[] packedStreams = new Stream[folder.NumPackedStreams];
            UInt64[] packedSizes   = new UInt64[folder.NumPackedStreams];
            for (ulong i = 0, currentPackPos = packPos; i < folder.NumPackedStreams; ++i)
            {
                UInt64 packedSize = streamsInfo.PackInfo.Sizes[packIndex + i];
                packedStreams[i] = new SubStream(this.stream, (long)currentPackPos, (long)packedSize);
                packedSizes[i]   = packedSize;
                currentPackPos  += packedSize;
            }

            // create output streams
            Stream[] outputStreams = new Stream[folder.NumOutStreamsTotal];

            // find primary output stream
            UInt64 primaryCoderIndex;
            UInt64 primaryOutStreamIndex;

            findPrimaryOutStreamIndex(folder, out primaryCoderIndex, out primaryOutStreamIndex);

            // start recursive stream creation
            return(createDecoderStreamForCoder(packedStreams, packedSizes, outputStreams, folder, primaryCoderIndex));
        }
Exemple #4
0
        private Stream createDecoderStreamForCoder(Stream[] packedStreams, UInt64[] packedSizes, Stream[] outputStreams, SevenZipHeader.Folder folder, UInt64 coderIndex)
        {
            // find starting in and out id for coder
            ulong inStreamId  = 0;
            ulong outStreamId = 0;

            for (ulong i = 0; i < coderIndex; ++i)
            {
                inStreamId  += folder.CodersInfo[i].NumInStreams;
                outStreamId += folder.CodersInfo[i].NumOutStreams;
            }

            // create input streams
            Stream[] inStreams = new Stream[folder.CodersInfo[coderIndex].NumInStreams];
            for (int i = 0; i < inStreams.Length; ++i, ++inStreamId)
            {
                Int64 bindPairIndex = folder.FindBindPairForInStream(inStreamId);
                if (bindPairIndex == -1)
                {
                    Int64 index = folder.FindPackedIndexForInStream(inStreamId);
                    if (index == -1)
                    {
                        throw new SevenZipException("Could not find input stream binding.");
                    }
                    inStreams[i] = packedStreams[index];
                }
                else
                {
                    UInt64 pairedOutIndex = folder.BindPairsInfo[bindPairIndex].OutIndex;
                    if (outputStreams[pairedOutIndex] != default(Stream))
                    {
                        throw new SevenZipException("Overlapping stream bindings are invalid.");
                    }

                    UInt64 subCoderIndex = findCoderIndexForOutStreamIndex(folder, pairedOutIndex);
                    inStreams[i] = createDecoderStreamForCoder(packedStreams, packedSizes, outputStreams, folder, subCoderIndex);

                    if (outputStreams[pairedOutIndex] != default(Stream))
                    {
                        throw new SevenZipException("Overlapping stream bindings are invalid.");
                    }

                    outputStreams[pairedOutIndex] = inStreams[i];
                }
            }

            var methodID = new SevenZipMethods.MethodID(folder.CodersInfo[coderIndex].CodecId);

            if (!SevenZipMethods.Supported.ContainsKey(methodID))
            {
                string codecName = SevenZipMethods.List.Where(id => id.Key == methodID).Select(id => id.Value).FirstOrDefault();
                throw new SevenZipException("Compression method `" + (codecName ?? "unknown") + "` not supported.");
            }

            return(Compression.Registry.GetDecoderStream(
                       SevenZipMethods.Supported[methodID],
                       inStreams,
                       folder.CodersInfo[coderIndex].Properties,
                       null,
                       (long)folder.UnPackSizes[outStreamId]));
        }
Exemple #5
0
        void buildFilesIndex()
        {
            // build empty index

            var filesInfo = header.RawHeader.FilesInfo;

            _Files = new SevenZipArchiveFile[filesInfo.NumFiles];
            for (ulong i = 0; i < filesInfo.NumFiles; ++i)
            {
                _Files[i] = new SevenZipArchiveFile();
            }
            Files = new ReadOnlyCollection <SevenZipArchiveFile>(_Files);

            // set properties that are contained in FileProperties structures

            foreach (var properties in filesInfo.Properties)
            {
                switch (properties.PropertyID)
                {
                case SevenZipHeader.PropertyID.kEmptyStream:
                    for (long i = 0; i < _Files.LongLength; ++i)
                    {
                        bool val = (properties as SevenZipHeader.PropertyEmptyStream).IsEmptyStream[i];
                        _Files[i].IsEmpty     = val;
                        _Files[i].IsDirectory = val;
                    }
                    break;

                case SevenZipHeader.PropertyID.kEmptyFile:
                    for (long i = 0, j = 0; i < _Files.LongLength; ++i)
                    {
                        if (_Files[i].IsEmpty)
                        {
                            bool val = (properties as SevenZipHeader.PropertyEmptyFile).IsEmptyFile[j++];
                            _Files[i].IsDirectory = !val;
                        }
                    }
                    break;

                case SevenZipHeader.PropertyID.kAnti:
                    for (long i = 0, j = 0; i < _Files.LongLength; ++i)
                    {
                        if (_Files[i].IsEmpty)
                        {
                            _Files[i].IsDeleted = (properties as SevenZipHeader.PropertyAnti).IsAnti[j++];
                        }
                    }
                    break;

                case SevenZipHeader.PropertyID.kMTime:
                    for (long i = 0; i < _Files.LongLength; ++i)
                    {
                        _Files[i].Time = (properties as SevenZipHeader.PropertyTime).Times[i];
                    }
                    break;

                case SevenZipHeader.PropertyID.kName:
                    for (long i = 0; i < _Files.LongLength; ++i)
                    {
                        _Files[i].Name = (properties as SevenZipHeader.PropertyName).Names[i];
                    }
                    break;

                case SevenZipHeader.PropertyID.kWinAttributes:
                    for (long i = 0; i < _Files.LongLength; ++i)
                    {
                        _Files[i].Attributes = (properties as SevenZipHeader.PropertyAttributes).Attributes[i];
                    }
                    break;
                }
            }

            // set output sizes from the overly complex 7zip headers

            var streamsInfo = header.RawHeader.MainStreamsInfo;
            var ui          = streamsInfo.UnPackInfo;
            var ssi         = streamsInfo.SubStreamsInfo;

            if (ui == null)
            {
                Trace.TraceWarning("7zip: Missing header information to calculate output file sizes.");
                return;
            }

            int upsIndex = 0;
            int upcIndex = 0;

            long fileIndex   = 0;
            long streamIndex = 0;

            for (long i = 0; i < (long)streamsInfo.UnPackInfo.NumFolders; ++i)
            {
                SevenZipHeader.Folder folder = ui.Folders[i];
                long ups = 1;
                if (ssi != null && ssi.NumUnPackStreamsInFolders.Any())
                {
                    ups = (long)ssi.NumUnPackStreamsInFolders[i];
                }
                if (ups == 0)
                {
                    throw new SevenZipException("Unexpected, no UnPackStream in Folder.");
                }

                UInt64 size = folder.GetUnPackSize();
                UInt32?crc  = folder.UnPackCRC;
                for (long j = 0; j < ups; ++j)
                {
                    if (ssi != null && ssi.UnPackSizes.Any())
                    {
                        if (upsIndex > ssi.UnPackSizes.Count())
                        {
                            throw new SevenZipException("Unexpected, missing UnPackSize entry(ies).");
                        }
                        size = ssi.UnPackSizes[upsIndex++];
                    }
                    else
                    {
                        if (ups > 1)
                        {
                            throw new SevenZipException("Missing SubStreamsInfo header chunk.");
                        }
                    }

                    if (crc == null || ups > 1)
                    {
                        if (ssi != null && ssi.Digests != null && (int)ssi.Digests.NumStreams() > upcIndex)
                        {
                            crc = ssi.Digests.CRCs[upcIndex];
                        }
                        upcIndex++;
                    }

                    while (_Files[fileIndex].IsEmpty)
                    {
                        if (++fileIndex >= _Files.LongLength)
                        {
                            throw new SevenZipException("Missing Files entries for defined sizes.");
                        }
                    }
                    _Files[fileIndex].Size        = size;
                    _Files[fileIndex].CRC         = crc;
                    _Files[fileIndex].UnPackIndex = (UInt64?)streamIndex;

                    fileIndex++;
                    streamIndex++;
                }
            }
        }