Crisis.Ionic.Zip.ZipEntry.ConstructExtraField C# (CSharp) Méthode

ConstructExtraField() private méthode

private ConstructExtraField ( bool forCentralDirectory ) : byte[]
forCentralDirectory bool
Résultat byte[]
        private byte[] ConstructExtraField(bool forCentralDirectory)
        {
            var listOfBlocks = new System.Collections.Generic.List<byte[]>();
            byte[] block;

            // Conditionally emit an extra field with Zip64 information.  If the
            // Zip64 option is Always, we emit the field, before knowing that it's
            // necessary.  Later, if it turns out this entry does not need zip64,
            // we'll set the header ID to rubbish and the data will be ignored.
            // This results in additional overhead metadata in the zip file, but
            // it will be small in comparison to the entry data.
            //
            // On the other hand if the Zip64 option is AsNecessary and it's NOT
            // for the central directory, then we do the same thing.  Or, if the
            // Zip64 option is AsNecessary and it IS for the central directory,
            // and the entry requires zip64, then emit the header.
            if (_container.Zip64 == Zip64Option.Always ||
                (_container.Zip64 == Zip64Option.AsNecessary &&
                 (!forCentralDirectory || _entryRequiresZip64.Value)))
            {
                // add extra field for zip64 here
                // workitem 7924
                int sz = 4 + (forCentralDirectory ? 28 : 16);
                block = new byte[sz];
                int i = 0;

                if (_presumeZip64 || forCentralDirectory)
                {
                    // HeaderId = always use zip64 extensions.
                    block[i++] = 0x01;
                    block[i++] = 0x00;
                }
                else
                {
                    // HeaderId = dummy data now, maybe set to 0x0001 (ZIP64) later.
                    block[i++] = 0x99;
                    block[i++] = 0x99;
                }

                // DataSize
                block[i++] = (byte)(sz - 4);  // decimal 28 or 16  (workitem 7924)
                block[i++] = 0x00;

                // The actual metadata - we may or may not have real values yet...

                // uncompressed size
                Array.Copy(BitConverter.GetBytes(_UncompressedSize), 0, block, i, 8);
                i += 8;
                // compressed size
                Array.Copy(BitConverter.GetBytes(_CompressedSize), 0, block, i, 8);
                i += 8;

                // workitem 7924 - only include this if the "extra" field is for
                // use in the central directory.  It is unnecessary and not useful
                // for local header; makes WinZip choke.
                if (forCentralDirectory)
                {
                    // relative offset
                    Array.Copy(BitConverter.GetBytes(_RelativeOffsetOfLocalHeader), 0, block, i, 8);
                    i += 8;

                    // starting disk number
                    Array.Copy(BitConverter.GetBytes(0), 0, block, i, 4);
                }
                listOfBlocks.Add(block);
            }


#if AESCRYPTO
            if (Encryption == EncryptionAlgorithm.WinZipAes128 ||
                Encryption == EncryptionAlgorithm.WinZipAes256)
            {
                block = new byte[4 + 7];
                int i = 0;
                // extra field for WinZip AES
                // header id
                block[i++] = 0x01;
                block[i++] = 0x99;

                // data size
                block[i++] = 0x07;
                block[i++] = 0x00;

                // vendor number
                block[i++] = 0x01;  // AE-1 - means "Verify CRC"
                block[i++] = 0x00;

                // vendor id "AE"
                block[i++] = 0x41;
                block[i++] = 0x45;

                // key strength
                int keystrength = GetKeyStrengthInBits(Encryption);
                if (keystrength == 128)
                    block[i] = 1;
                else if (keystrength == 256)
                    block[i] = 3;
                else
                    block[i] = 0xFF;
                i++;

                // actual compression method
                block[i++] = (byte)(_CompressionMethod & 0x00FF);
                block[i++] = (byte)(_CompressionMethod & 0xFF00);

                listOfBlocks.Add(block);
            }
#endif

            if (_ntfsTimesAreSet && _emitNtfsTimes)
            {
                block = new byte[32 + 4];
                // HeaderId   2 bytes    0x000a == NTFS times
                // Datasize   2 bytes    32
                // reserved   4 bytes    ?? don't care
                // timetag    2 bytes    0x0001 == NTFS time
                // size       2 bytes    24 == 8 bytes each for ctime, mtime, atime
                // mtime      8 bytes    win32 ticks since win32epoch
                // atime      8 bytes    win32 ticks since win32epoch
                // ctime      8 bytes    win32 ticks since win32epoch
                int i = 0;
                // extra field for NTFS times
                // header id
                block[i++] = 0x0a;
                block[i++] = 0x00;

                // data size
                block[i++] = 32;
                block[i++] = 0;

                i += 4; // reserved

                // time tag
                block[i++] = 0x01;
                block[i++] = 0x00;

                // data size (again)
                block[i++] = 24;
                block[i++] = 0;

                Int64 z = _Mtime.ToFileTime();
                Array.Copy(BitConverter.GetBytes(z), 0, block, i, 8);
                i += 8;
                z = _Atime.ToFileTime();
                Array.Copy(BitConverter.GetBytes(z), 0, block, i, 8);
                i += 8;
                z = _Ctime.ToFileTime();
                Array.Copy(BitConverter.GetBytes(z), 0, block, i, 8);
                i += 8;

                listOfBlocks.Add(block);
            }

            if (_ntfsTimesAreSet && _emitUnixTimes)
            {
                int len = 5 + 4;
                if (!forCentralDirectory) len += 8;

                block = new byte[len];
                // local form:
                // --------------
                // HeaderId   2 bytes    0x5455 == unix timestamp
                // Datasize   2 bytes    13
                // flags      1 byte     7 (low three bits all set)
                // mtime      4 bytes    seconds since unix epoch
                // atime      4 bytes    seconds since unix epoch
                // ctime      4 bytes    seconds since unix epoch
                //
                // central directory form:
                //---------------------------------
                // HeaderId   2 bytes    0x5455 == unix timestamp
                // Datasize   2 bytes    5
                // flags      1 byte     7 (low three bits all set)
                // mtime      4 bytes    seconds since unix epoch
                //
                int i = 0;
                // extra field for "unix" times
                // header id
                block[i++] = 0x55;
                block[i++] = 0x54;

                // data size
                block[i++] = unchecked((byte)(len - 4));
                block[i++] = 0;

                // flags
                block[i++] = 0x07;

                Int32 z = unchecked((int)((_Mtime - _unixEpoch).TotalSeconds));
                Array.Copy(BitConverter.GetBytes(z), 0, block, i, 4);
                i += 4;
                if (!forCentralDirectory)
                {
                    z = unchecked((int)((_Atime - _unixEpoch).TotalSeconds));
                    Array.Copy(BitConverter.GetBytes(z), 0, block, i, 4);
                    i += 4;
                    z = unchecked((int)((_Ctime - _unixEpoch).TotalSeconds));
                    Array.Copy(BitConverter.GetBytes(z), 0, block, i, 4);
                    i += 4;
                }
                listOfBlocks.Add(block);
            }


            // inject other blocks here...


            // concatenate any blocks we've got:
            byte[] aggregateBlock = null;
            if (listOfBlocks.Count > 0)
            {
                int totalLength = 0;
                int i, current = 0;
                for (i = 0; i < listOfBlocks.Count; i++)
                    totalLength += listOfBlocks[i].Length;
                aggregateBlock = new byte[totalLength];
                for (i = 0; i < listOfBlocks.Count; i++)
                {
                    System.Array.Copy(listOfBlocks[i], 0, aggregateBlock, current, listOfBlocks[i].Length);
                    current += listOfBlocks[i].Length;
                }
            }

            return aggregateBlock;
        }
ZipEntry