Esempio n. 1
0
        // There is a small chance that something very weird could happen here. The code calling into this function
        // will ask for a value from the extra field if the field was masked with FF's. It's theoretically possible
        // that a field was FF's legitimately, and the writer didn't decide to write the corresponding extra field.
        // Also, at the same time, other fields were masked with FF's to indicate looking in the zip64 record.
        // Then, the search for the zip64 record will fail because the expected size is wrong,
        // and a nulled out Zip64ExtraField will be returned. Thus, even though there was Zip64 data,
        // it will not be used. It is questionable whether this situation is possible to detect

        // unlike the other functions that have try-pattern semantics, these functions always return a
        // Zip64ExtraField. If a Zip64 extra field actually doesn't exist, all of the fields in the
        // returned struct will be null
        //
        // If there are more than one Zip64 extra fields, we take the first one that has the expected size
        //
        public static Zip64ExtraField GetJustZip64Block(Stream extraFieldStream,
                                                        bool readUncompressedSize, bool readCompressedSize,
                                                        bool readLocalHeaderOffset, bool readStartDiskNumber)
        {
            Zip64ExtraField zip64Field;

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

            zip64Field = new Zip64ExtraField();

            zip64Field._compressedSize    = null;
            zip64Field._uncompressedSize  = null;
            zip64Field._localHeaderOffset = null;
            zip64Field._startDiskNumber   = null;

            return(zip64Field);
        }
        public static bool TryReadBlock(BinaryReader reader, long endExtraField, out ZipGenericExtraField field)
        {
            field = new ZipGenericExtraField();

            if (endExtraField - reader.BaseStream.Position < 4)
            {
                return(false);
            }

            field._tag  = reader.ReadUInt16();
            field._size = reader.ReadUInt16();

            if (endExtraField - reader.BaseStream.Position < field._size)
            {
                return(false);
            }

            field._data = reader.ReadBytes(field._size);
            return(true);
        }
Esempio n. 3
0
        private static bool TryGetZip64BlockFromGenericExtraField(ZipGenericExtraField extraField,
                                                                  bool readUncompressedSize, bool readCompressedSize,
                                                                  bool readLocalHeaderOffset, bool readStartDiskNumber,
                                                                  out Zip64ExtraField zip64Block)
        {
            zip64Block = new Zip64ExtraField();

            zip64Block._compressedSize    = null;
            zip64Block._uncompressedSize  = null;
            zip64Block._localHeaderOffset = null;
            zip64Block._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 (BinaryReader reader = new BinaryReader(ms))
                {
                    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 ZipArchiveException("FieldTooBigUncompressedSize");
                    }
                    if (zip64Block._compressedSize < 0)
                    {
                        throw new ZipArchiveException("FieldTooBigCompressedSize");
                    }
                    if (zip64Block._localHeaderOffset < 0)
                    {
                        throw new ZipArchiveException("FieldTooBigLocalHeaderOffset");
                    }
                    if (zip64Block._startDiskNumber < 0)
                    {
                        throw new ZipArchiveException("FieldTooBigStartDiskNumber");
                    }

                    return(true);
                }
            }
            finally
            {
                if (ms != null)
                {
                    ms.Dispose();
                }
            }
        }
        private static bool TryGetZip64BlockFromGenericExtraField(ZipGenericExtraField extraField,
                                                                  bool readUncompressedSize, bool readCompressedSize,
                                                                  bool readLocalHeaderOffset, bool readStartDiskNumber,
                                                                  out Zip64ExtraField zip64Block)
        {
            zip64Block = new Zip64ExtraField();

            zip64Block._compressedSize    = null;
            zip64Block._uncompressedSize  = null;
            zip64Block._localHeaderOffset = null;
            zip64Block._startDiskNumber   = null;

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

            MemoryStream ms = null;

            try
            {
                ms = new MemoryStream(extraField.Data);
                using (BinaryReader reader = new BinaryReader(ms))
                {
                    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 (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();
                    }

                    if (zip64Block._uncompressedSize < 0)
                    {
                        throw new ZipArchiveException("FieldTooBigUncompressedSize");
                    }
                    if (zip64Block._compressedSize < 0)
                    {
                        throw new ZipArchiveException("FieldTooBigCompressedSize");
                    }
                    if (zip64Block._localHeaderOffset < 0)
                    {
                        throw new ZipArchiveException("FieldTooBigLocalHeaderOffset");
                    }
                    if (zip64Block._startDiskNumber < 0)
                    {
                        throw new ZipArchiveException("FieldTooBigStartDiskNumber");
                    }

                    return(true);
                }
            }
            finally
            {
                if (ms != null)
                {
                    ms.Dispose();
                }
            }
        }