|
3 | 3 | using ICSharpCode.SharpZipLib.Zip.Compression;
|
4 | 4 | using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
|
5 | 5 | using System;
|
| 6 | +using System.Diagnostics; |
6 | 7 | using System.IO;
|
7 | 8 |
|
8 | 9 | namespace ICSharpCode.SharpZipLib.Zip
|
@@ -181,31 +182,12 @@ public ZipEntry GetNextEntry()
|
181 | 182 | CloseEntry();
|
182 | 183 | }
|
183 | 184 |
|
184 |
| - int header = inputBuffer.ReadLeInt(); |
185 |
| - |
186 |
| - if (header == ZipConstants.CentralHeaderSignature || |
187 |
| - header == ZipConstants.EndOfCentralDirectorySignature || |
188 |
| - header == ZipConstants.CentralHeaderDigitalSignature || |
189 |
| - header == ZipConstants.ArchiveExtraDataSignature || |
190 |
| - header == ZipConstants.Zip64CentralFileHeaderSignature) |
| 185 | + if (!SkipUntilNextEntry()) |
191 | 186 | {
|
192 |
| - // No more individual entries exist |
193 | 187 | Dispose();
|
194 | 188 | return null;
|
195 | 189 | }
|
196 | 190 |
|
197 |
| - // -jr- 07-Dec-2003 Ignore spanning temporary signatures if found |
198 |
| - // Spanning signature is same as descriptor signature and is untested as yet. |
199 |
| - if ((header == ZipConstants.SpanningTempSignature) || (header == ZipConstants.SpanningSignature)) |
200 |
| - { |
201 |
| - header = inputBuffer.ReadLeInt(); |
202 |
| - } |
203 |
| - |
204 |
| - if (header != ZipConstants.LocalHeaderSignature) |
205 |
| - { |
206 |
| - throw new ZipException("Wrong Local header signature: 0x" + String.Format("{0:X}", header)); |
207 |
| - } |
208 |
| - |
209 | 191 | var versionRequiredToExtract = (short)inputBuffer.ReadLeShort();
|
210 | 192 |
|
211 | 193 | flags = inputBuffer.ReadLeShort();
|
@@ -303,6 +285,54 @@ public ZipEntry GetNextEntry()
|
303 | 285 | return entry;
|
304 | 286 | }
|
305 | 287 |
|
| 288 | + /// <summary> |
| 289 | + /// Reads bytes from the input stream until either a local file header signature, or another signature |
| 290 | + /// indicating that no more entries should be present, is found. |
| 291 | + /// </summary> |
| 292 | + /// <exception cref="ZipException">Thrown if the end of the input stream is reached without any signatures found</exception> |
| 293 | + /// <returns>Returns whether the found signature is for a local entry header</returns> |
| 294 | + private bool SkipUntilNextEntry() |
| 295 | + { |
| 296 | + // First let's skip all null bytes since it's the sane padding to add when updating an entry with smaller size |
| 297 | + var paddingSkipped = 0; |
| 298 | + while(inputBuffer.ReadLeByte() == 0) { |
| 299 | + paddingSkipped++; |
| 300 | + } |
| 301 | + |
| 302 | + // Last byte read was not actually consumed, restore the offset |
| 303 | + inputBuffer.Available += 1; |
| 304 | + if(paddingSkipped > 0) { |
| 305 | + Debug.WriteLine("Skipped {0} null byte(s) before reading signature", paddingSkipped); |
| 306 | + } |
| 307 | + |
| 308 | + var offset = 0; |
| 309 | + // Read initial header quad directly after the last entry |
| 310 | + var header = (uint)inputBuffer.ReadLeInt(); |
| 311 | + do |
| 312 | + { |
| 313 | + switch (header) |
| 314 | + { |
| 315 | + case ZipConstants.CentralHeaderSignature: |
| 316 | + case ZipConstants.EndOfCentralDirectorySignature: |
| 317 | + case ZipConstants.CentralHeaderDigitalSignature: |
| 318 | + case ZipConstants.ArchiveExtraDataSignature: |
| 319 | + case ZipConstants.Zip64CentralFileHeaderSignature: |
| 320 | + Debug.WriteLine("Non-entry signature found at offset {0,2}: 0x{1:x8}", offset, header); |
| 321 | + // No more individual entries exist |
| 322 | + return false; |
| 323 | + |
| 324 | + case ZipConstants.LocalHeaderSignature: |
| 325 | + Debug.WriteLine("Entry local header signature found at offset {0,2}: 0x{1:x8}", offset, header); |
| 326 | + return true; |
| 327 | + default: |
| 328 | + // Current header quad did not match any signature, shift in another byte |
| 329 | + header = (uint) (inputBuffer.ReadLeByte() << 24) | (header >> 8); |
| 330 | + offset++; |
| 331 | + break; |
| 332 | + } |
| 333 | + } while (true); // Loop until we either get an EOF exception or we find the next signature |
| 334 | + } |
| 335 | + |
306 | 336 | /// <summary>
|
307 | 337 | /// Read data descriptor at the end of compressed data.
|
308 | 338 | /// </summary>
|
@@ -400,6 +430,7 @@ public void CloseEntry()
|
400 | 430 |
|
401 | 431 | if ((inputBuffer.Available > csize) && (csize >= 0))
|
402 | 432 | {
|
| 433 | + // Buffer can contain entire entry data. Internally offsetting position inside buffer |
403 | 434 | inputBuffer.Available = (int)((long)inputBuffer.Available - csize);
|
404 | 435 | }
|
405 | 436 | else
|
|
0 commit comments