Example #1
0
        internal static Zip64ExtraField GetJustZip64Block(Stream extraFieldStream,
                                                          bool readUncompressedSize, bool readCompressedSize,
                                                          bool readLocalHeaderOffset, bool readStartDiskNumber)
        {
            Zip64ExtraField zip64Field;

            using (var reader = new BinaryReader(extraFieldStream, _utf8EncodingNoBOM))
            {
                while (ZipGenericExtraField.TryReadBlock(reader, extraFieldStream.Length, out var currentExtraField))
                {
                    if (TryGetZip64BlockFromGenericExtraField(currentExtraField, readUncompressedSize,
                                                              readCompressedSize, readLocalHeaderOffset, readStartDiskNumber, out zip64Field))
                    {
                        return(zip64Field);
                    }
                }
            }

            zip64Field = new Zip64ExtraField
            {
                CompressedSize    = null,
                UncompressedSize  = null,
                LocalHeaderOffset = null,
                StartDiskNumber   = null
            };

            return(zip64Field);
        }
Example #2
0
        // shouldn't ever read the byte at position endExtraField
        // assumes we are positioned at the beginning of an extra field subfield
        internal static bool TryReadBlock(BinaryReader reader, long endExtraField, out ZipGenericExtraField field)
        {
            field = new ZipGenericExtraField();

            // not enough bytes to read tag + size
            if (endExtraField - reader.BaseStream.Position < 4)
            {
                return(false);
            }

            field.Tag  = reader.ReadUInt16();
            field.Size = reader.ReadUInt16();

            // not enough bytes to read the data
            if (endExtraField - reader.BaseStream.Position < field.Size)
            {
                return(false);
            }

            field.Data = reader.ReadBytes(field.Size);
            return(true);
        }
Example #3
0
        private static bool TryGetZip64BlockFromGenericExtraField(ZipGenericExtraField extraField,
                                                                  bool readUncompressedSize, bool readCompressedSize,
                                                                  bool readLocalHeaderOffset, bool readStartDiskNumber,
                                                                  out Zip64ExtraField zip64Block)
        {
            zip64Block = new Zip64ExtraField
            {
                CompressedSize    = null,
                UncompressedSize  = null,
                LocalHeaderOffset = null,
                StartDiskNumber   = null
            };

            if (extraField.Tag != TagConstant)
            {
                return(false);
            }

            // this pattern needed because nested using blocks trigger CA2202
            MemoryStream?ms = null;

            try
            {
                ms = new MemoryStream(extraField.Data);
                using var reader = new BinaryReader(ms);

                // Why did they do this and how does it still work?!
                ms = null;

                zip64Block._size = extraField.Size;

                ushort expectedSize = 0;

                if (readUncompressedSize)
                {
                    expectedSize += 8;
                }
                if (readCompressedSize)
                {
                    expectedSize += 8;
                }
                if (readLocalHeaderOffset)
                {
                    expectedSize += 8;
                }
                if (readStartDiskNumber)
                {
                    expectedSize += 4;
                }

                // if it is not the expected size, perhaps there is another extra field that matches
                if (expectedSize != zip64Block._size)
                {
                    return(false);
                }

                if (readUncompressedSize)
                {
                    zip64Block.UncompressedSize = reader.ReadInt64();
                }
                if (readCompressedSize)
                {
                    zip64Block.CompressedSize = reader.ReadInt64();
                }
                if (readLocalHeaderOffset)
                {
                    zip64Block.LocalHeaderOffset = reader.ReadInt64();
                }
                if (readStartDiskNumber)
                {
                    zip64Block.StartDiskNumber = reader.ReadInt32();
                }

                // original values are unsigned, so implies value is too big to fit in signed integer
                if (zip64Block.UncompressedSize < 0)
                {
                    throw new InvalidDataException(SR.FieldTooBigUncompressedSize);
                }
                if (zip64Block.CompressedSize < 0)
                {
                    throw new InvalidDataException(SR.FieldTooBigCompressedSize);
                }
                if (zip64Block.LocalHeaderOffset < 0)
                {
                    throw new InvalidDataException(SR.FieldTooBigLocalHeaderOffset);
                }
                if (zip64Block.StartDiskNumber < 0)
                {
                    throw new InvalidDataException(SR.FieldTooBigStartDiskNumber);
                }

                return(true);
            }
            finally
            {
                ms?.Dispose();
            }
        }