/// <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]); } }
/// <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; } }
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); } }
/// <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)); }