예제 #1
0
 /// <summary>
 ///   This initializes the cipher with the given password.
 ///   See AppNote.txt for details.
 /// </summary>
 ///
 /// <param name="passphrase">
 ///   The passphrase for encrypting or decrypting with this cipher.
 /// </param>
 ///
 /// <remarks>
 /// <code>
 /// Step 1 - Initializing the encryption keys
 /// -----------------------------------------
 /// Start with these keys:
 /// Key(0) := 305419896 (0x12345678)
 /// Key(1) := 591751049 (0x23456789)
 /// Key(2) := 878082192 (0x34567890)
 ///
 /// Then, initialize the keys with a password:
 ///
 /// loop for i from 0 to length(password)-1
 ///     update_keys(password(i))
 /// end loop
 ///
 /// Where update_keys() is defined as:
 ///
 /// update_keys(char):
 ///   Key(0) := crc32(key(0),char)
 ///   Key(1) := Key(1) + (Key(0) bitwiseAND 000000ffH)
 ///   Key(1) := Key(1) * 134775813 + 1
 ///   Key(2) := crc32(key(2),key(1) rightshift 24)
 /// end update_keys
 ///
 /// Where crc32(old_crc,char) is a routine that given a CRC value and a
 /// character, returns an updated CRC value after applying the CRC-32
 /// algorithm described elsewhere in this document.
 ///
 /// </code>
 ///
 /// <para>
 ///   After the keys are initialized, then you can use the cipher to
 ///   encrypt the plaintext.
 /// </para>
 ///
 /// <para>
 ///   Essentially we encrypt the password with the keys, then discard the
 ///   ciphertext for the password. This initializes the keys for later use.
 /// </para>
 ///
 /// </remarks>
 public void InitCipher(string passphrase)
 {
     byte[] p = SharedUtilities.StringToByteArray(passphrase);
     for (int i = 0; i < passphrase.Length; i++)
     {
         UpdateKeys(p[i]);
     }
 }
예제 #2
0
 /// <summary>
 ///   This is a name-based indexer into the Zip archive.
 /// </summary>
 ///
 /// <remarks>
 /// <para>
 ///   This property is read-only.
 /// </para>
 ///
 /// <para>
 ///   The <see cref="CaseSensitiveRetrieval"/> property on the <c>ZipFile</c>
 ///   determines whether retrieval via this indexer is done via case-sensitive
 ///   comparisons. By default, retrieval is not case sensitive.  This makes
 ///   sense on Windows, in which filesystems are not case sensitive.
 /// </para>
 ///
 /// <para>
 ///   Regardless of case-sensitivity, it is not always the case that
 ///   <c>this[value].FileName == value</c>. In other words, the <c>FileName</c>
 ///   property of the <c>ZipEntry</c> retrieved with this indexer, may or may
 ///   not be equal to the index value.
 /// </para>
 ///
 /// <para>
 ///   This is because DotNetZip performs a normalization of filenames passed to
 ///   this indexer, before attempting to retrieve the item.  That normalization
 ///   includes: removal of a volume letter and colon, swapping backward slashes
 ///   for forward slashes.  So, <c>zip["dir1\\entry1.txt"].FileName ==
 ///   "dir1/entry.txt"</c>.
 /// </para>
 ///
 /// <para>
 ///   Directory entries in the zip file may be retrieved via this indexer only
 ///   with names that have a trailing slash. DotNetZip automatically appends a
 ///   trailing slash to the names of any directory entries added to a zip.
 /// </para>
 ///
 /// </remarks>
 ///
 /// <example>
 /// This example extracts only the entries in a zip file that are .txt files.
 /// <code>
 /// using (ZipFile zip = ZipFile.Read("PackedDocuments.zip"))
 /// {
 ///   foreach (string s1 in zip.EntryFilenames)
 ///   {
 ///     if (s1.EndsWith(".txt"))
 ///       zip[s1].Extract("textfiles");
 ///   }
 /// }
 /// </code>
 /// <code lang="VB">
 ///   Using zip As ZipFile = ZipFile.Read("PackedDocuments.zip")
 ///       Dim s1 As String
 ///       For Each s1 In zip.EntryFilenames
 ///           If s1.EndsWith(".txt") Then
 ///               zip(s1).Extract("textfiles")
 ///           End If
 ///       Next
 ///   End Using
 /// </code>
 /// </example>
 ///
 /// <exception cref="System.ArgumentException">
 ///   Thrown if the caller attempts to assign a non-null value to the indexer.
 /// </exception>
 ///
 /// <param name="fileName">
 ///   The name of the file, including any directory path, to retrieve from the
 ///   zip.  The filename match is not case-sensitive by default; you can use the
 ///   <see cref="CaseSensitiveRetrieval"/> property to change this behavior. The
 ///   pathname can use forward-slashes or backward slashes.
 /// </param>
 ///
 /// <returns>
 ///   The <c>ZipEntry</c> within the Zip archive, given by the specified
 ///   filename. If the named entry does not exist in the archive, this indexer
 ///   returns <c>null</c> (<c>Nothing</c> in VB).
 /// </returns>
 ///
 public ZipEntry this[String fileName]
 {
     get
     {
         var key = SharedUtilities.NormalizePathForUseInZipFile(fileName);
         if (_entries.ContainsKey(key))
             return _entries[key];
         // workitem 11056
         key = key.Replace("/", "\\");
         if (_entries.ContainsKey(key))
             return _entries[key];
         return null;
     }
 }
예제 #3
0
        private static void ReadIntoInstance(ZipFile zf)
        {
            Stream s = zf.ReadStream;

            try
            {
                if (!s.CanSeek)
                {
                    ReadIntoInstance_Orig(zf);
                    return;
                }

                // change for workitem 8098
                //zf._originPosition = s.Position;

                // Try reading the central directory, rather than scanning the file.

                uint datum = ReadFirstFourBytes(s);

                if (datum == ZipConstants.EndOfCentralDirectorySignature)
                {
                    return;
                }


                // start at the end of the file...
                // seek backwards a bit, then look for the EoCD signature.
                int  nTries  = 0;
                bool success = false;

                // The size of the end-of-central-directory-footer plus 2 bytes is 18.
                // This implies an archive comment length of 0.  We'll add a margin of
                // safety and start "in front" of that, when looking for the
                // EndOfCentralDirectorySignature
                long posn        = s.Length - 64;
                long maxSeekback = Math.Max(s.Length - 0x4000, 10);
                do
                {
                    if (posn < 0)
                    {
                        posn = 0;            // BOF
                    }
                    s.Seek(posn, SeekOrigin.Begin);
                    long bytesRead = SharedUtilities.FindSignature(s, (int)ZipConstants.EndOfCentralDirectorySignature);
                    if (bytesRead != -1)
                    {
                        success = true;
                    }
                    else
                    {
                        if (posn == 0)
                        {
                            break;          // started at the BOF and found nothing
                        }
                        nTries++;
                        // Weird: with NETCF, negative offsets from SeekOrigin.End DO
                        // NOT WORK. So rather than seek a negative offset, we seek
                        // from SeekOrigin.Begin using a smaller number.
                        posn -= (32 * (nTries + 1) * nTries);
                    }
                }while (!success && posn > maxSeekback);

                if (success)
                {
                    // workitem 8299
                    zf._locEndOfCDS = s.Position - 4;

                    byte[] block = new byte[16];
                    s.Read(block, 0, block.Length);

                    zf._diskNumberWithCd = BitConverter.ToUInt16(block, 2);

                    if (zf._diskNumberWithCd == 0xFFFF)
                    {
                        throw new ZipException("Spanned archives with more than 65534 segments are not supported at this time.");
                    }

                    zf._diskNumberWithCd++; // I think the number in the file differs from reality by 1

                    int i = 12;

                    uint offset32 = (uint)BitConverter.ToUInt32(block, i);
                    if (offset32 == 0xFFFFFFFF)
                    {
                        Zip64SeekToCentralDirectory(zf);
                    }
                    else
                    {
                        // change for workitem 8098
                        s.Seek(offset32, SeekOrigin.Begin);
                    }

                    ReadCentralDirectory(zf);
                }
                else
                {
                    // Could not find the central directory.
                    // Fallback to the old method.
                    // workitem 8098: ok
                    //s.Seek(zf._originPosition, SeekOrigin.Begin);
                    s.Seek(0L, SeekOrigin.Begin);
                    ReadIntoInstance_Orig(zf);
                }
            }
            catch (Exception ex1)
            {
                throw new ZipException("Cannot read that as a ZipFile", ex1);
            }
        }
예제 #4
0
 /// <summary>
 ///   Returns true if an entry by the given name exists in the ZipFile.
 /// </summary>
 ///
 /// <param name='name'>the name of the entry to find</param>
 /// <returns>true if an entry with the given name exists; otherwise false.
 /// </returns>
 public bool ContainsEntry(string name)
 {
     // workitem 12534
     return _entries.ContainsKey(SharedUtilities.NormalizePathForUseInZipFile(name));
 }