kopia lustrzana https://github.com/dl2alf/AirScout
352 wiersze
13 KiB
C#
352 wiersze
13 KiB
C#
// ZipFile.Check.cs
|
|
// ------------------------------------------------------------------
|
|
//
|
|
// Copyright (c) 2009-2011 Dino Chiesa.
|
|
// All rights reserved.
|
|
//
|
|
// This code module is part of DotNetZip, a zipfile class library.
|
|
//
|
|
// ------------------------------------------------------------------
|
|
//
|
|
// This code is licensed under the Microsoft Public License.
|
|
// See the file License.txt for the license details.
|
|
// More info on: http://dotnetzip.codeplex.com
|
|
//
|
|
// ------------------------------------------------------------------
|
|
//
|
|
// last saved (in emacs):
|
|
// Time-stamp: <2011-July-31 14:40:50>
|
|
//
|
|
// ------------------------------------------------------------------
|
|
//
|
|
// This module defines the methods for doing Checks on zip files.
|
|
// These are not necessary to include in the Reduced or CF
|
|
// version of the library.
|
|
//
|
|
// ------------------------------------------------------------------
|
|
//
|
|
|
|
|
|
using System;
|
|
using System.IO;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Ionic.Zip
|
|
{
|
|
public partial class ZipFile
|
|
{
|
|
/// <summary>
|
|
/// Checks a zip file to see if its directory is consistent.
|
|
/// </summary>
|
|
///
|
|
/// <remarks>
|
|
///
|
|
/// <para>
|
|
/// In cases of data error, the directory within a zip file can get out
|
|
/// of synch with the entries in the zip file. This method checks the
|
|
/// given zip file and returns true if this has occurred.
|
|
/// </para>
|
|
///
|
|
/// <para> This method may take a long time to run for large zip files. </para>
|
|
///
|
|
/// <para>
|
|
/// This method is not supported in the Reduced or Compact Framework
|
|
/// versions of DotNetZip.
|
|
/// </para>
|
|
///
|
|
/// <para>
|
|
/// Developers using COM can use the <see
|
|
/// cref="ComHelper.CheckZip(String)">ComHelper.CheckZip(String)</see>
|
|
/// method.
|
|
/// </para>
|
|
///
|
|
/// </remarks>
|
|
///
|
|
/// <param name="zipFileName">The filename to of the zip file to check.</param>
|
|
///
|
|
/// <returns>true if the named zip file checks OK. Otherwise, false. </returns>
|
|
///
|
|
/// <seealso cref="FixZipDirectory(string)"/>
|
|
/// <seealso cref="CheckZip(string,bool,System.IO.TextWriter)"/>
|
|
public static bool CheckZip(string zipFileName)
|
|
{
|
|
return CheckZip(zipFileName, false, null);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Checks a zip file to see if its directory is consistent,
|
|
/// and optionally fixes the directory if necessary.
|
|
/// </summary>
|
|
///
|
|
/// <remarks>
|
|
///
|
|
/// <para>
|
|
/// In cases of data error, the directory within a zip file can get out of
|
|
/// synch with the entries in the zip file. This method checks the given
|
|
/// zip file, and returns true if this has occurred. It also optionally
|
|
/// fixes the zipfile, saving the fixed copy in <em>Name</em>_Fixed.zip.
|
|
/// </para>
|
|
///
|
|
/// <para>
|
|
/// This method may take a long time to run for large zip files. It
|
|
/// will take even longer if the file actually needs to be fixed, and if
|
|
/// <c>fixIfNecessary</c> is true.
|
|
/// </para>
|
|
///
|
|
/// <para>
|
|
/// This method is not supported in the Reduced or Compact
|
|
/// Framework versions of DotNetZip.
|
|
/// </para>
|
|
///
|
|
/// </remarks>
|
|
///
|
|
/// <param name="zipFileName">The filename to of the zip file to check.</param>
|
|
///
|
|
/// <param name="fixIfNecessary">If true, the method will fix the zip file if
|
|
/// necessary.</param>
|
|
///
|
|
/// <param name="writer">
|
|
/// a TextWriter in which messages generated while checking will be written.
|
|
/// </param>
|
|
///
|
|
/// <returns>true if the named zip is OK; false if the file needs to be fixed.</returns>
|
|
///
|
|
/// <seealso cref="CheckZip(string)"/>
|
|
/// <seealso cref="FixZipDirectory(string)"/>
|
|
public static bool CheckZip(string zipFileName, bool fixIfNecessary,
|
|
TextWriter writer)
|
|
|
|
{
|
|
ZipFile zip1 = null, zip2 = null;
|
|
bool isOk = true;
|
|
try
|
|
{
|
|
zip1 = new ZipFile();
|
|
zip1.FullScan = true;
|
|
zip1.Initialize(zipFileName);
|
|
|
|
zip2 = ZipFile.Read(zipFileName);
|
|
|
|
foreach (var e1 in zip1)
|
|
{
|
|
foreach (var e2 in zip2)
|
|
{
|
|
if (e1.FileName == e2.FileName)
|
|
{
|
|
if (e1._RelativeOffsetOfLocalHeader != e2._RelativeOffsetOfLocalHeader)
|
|
{
|
|
isOk = false;
|
|
if (writer != null)
|
|
writer.WriteLine("{0}: mismatch in RelativeOffsetOfLocalHeader (0x{1:X16} != 0x{2:X16})",
|
|
e1.FileName, e1._RelativeOffsetOfLocalHeader,
|
|
e2._RelativeOffsetOfLocalHeader);
|
|
}
|
|
if (e1._CompressedSize != e2._CompressedSize)
|
|
{
|
|
isOk = false;
|
|
if (writer != null)
|
|
writer.WriteLine("{0}: mismatch in CompressedSize (0x{1:X16} != 0x{2:X16})",
|
|
e1.FileName, e1._CompressedSize,
|
|
e2._CompressedSize);
|
|
}
|
|
if (e1._UncompressedSize != e2._UncompressedSize)
|
|
{
|
|
isOk = false;
|
|
if (writer != null)
|
|
writer.WriteLine("{0}: mismatch in UncompressedSize (0x{1:X16} != 0x{2:X16})",
|
|
e1.FileName, e1._UncompressedSize,
|
|
e2._UncompressedSize);
|
|
}
|
|
if (e1.CompressionMethod != e2.CompressionMethod)
|
|
{
|
|
isOk = false;
|
|
if (writer != null)
|
|
writer.WriteLine("{0}: mismatch in CompressionMethod (0x{1:X4} != 0x{2:X4})",
|
|
e1.FileName, e1.CompressionMethod,
|
|
e2.CompressionMethod);
|
|
}
|
|
if (e1.Crc != e2.Crc)
|
|
{
|
|
isOk = false;
|
|
if (writer != null)
|
|
writer.WriteLine("{0}: mismatch in Crc32 (0x{1:X4} != 0x{2:X4})",
|
|
e1.FileName, e1.Crc,
|
|
e2.Crc);
|
|
}
|
|
|
|
// found a match, so stop the inside loop
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
zip2.Dispose();
|
|
zip2 = null;
|
|
|
|
if (!isOk && fixIfNecessary)
|
|
{
|
|
string newFileName = Path.GetFileNameWithoutExtension(zipFileName);
|
|
newFileName = System.String.Format("{0}_fixed.zip", newFileName);
|
|
zip1.Save(newFileName);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (zip1 != null) zip1.Dispose();
|
|
if (zip2 != null) zip2.Dispose();
|
|
}
|
|
return isOk;
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Rewrite the directory within a zipfile.
|
|
/// </summary>
|
|
///
|
|
/// <remarks>
|
|
///
|
|
/// <para>
|
|
/// In cases of data error, the directory in a zip file can get out of
|
|
/// synch with the entries in the zip file. This method attempts to fix
|
|
/// the zip file if this has occurred.
|
|
/// </para>
|
|
///
|
|
/// <para> This can take a long time for large zip files. </para>
|
|
///
|
|
/// <para> This won't work if the zip file uses a non-standard
|
|
/// code page - neither IBM437 nor UTF-8. </para>
|
|
///
|
|
/// <para>
|
|
/// This method is not supported in the Reduced or Compact Framework
|
|
/// versions of DotNetZip.
|
|
/// </para>
|
|
///
|
|
/// <para>
|
|
/// Developers using COM can use the <see
|
|
/// cref="ComHelper.FixZipDirectory(String)">ComHelper.FixZipDirectory(String)</see>
|
|
/// method.
|
|
/// </para>
|
|
///
|
|
/// </remarks>
|
|
///
|
|
/// <param name="zipFileName">The filename to of the zip file to fix.</param>
|
|
///
|
|
/// <seealso cref="CheckZip(string)"/>
|
|
/// <seealso cref="CheckZip(string,bool,System.IO.TextWriter)"/>
|
|
public static void FixZipDirectory(string zipFileName)
|
|
{
|
|
using (var zip = new ZipFile())
|
|
{
|
|
zip.FullScan = true;
|
|
zip.Initialize(zipFileName);
|
|
zip.Save(zipFileName);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Verify the password on a zip file.
|
|
/// </summary>
|
|
///
|
|
/// <remarks>
|
|
/// <para>
|
|
/// Keep in mind that passwords in zipfiles are applied to
|
|
/// zip entries, not to the entire zip file. So testing a
|
|
/// zipfile for a particular password doesn't work in the
|
|
/// general case. On the other hand, it's often the case
|
|
/// that a single password will be used on all entries in a
|
|
/// zip file. This method works for that case.
|
|
/// </para>
|
|
/// <para>
|
|
/// There is no way to check a password without doing the
|
|
/// decryption. So this code decrypts and extracts the given
|
|
/// zipfile into <see cref="System.IO.Stream.Null"/>
|
|
/// </para>
|
|
/// </remarks>
|
|
///
|
|
/// <param name="zipFileName">The filename to of the zip file to fix.</param>
|
|
///
|
|
/// <param name="password">The password to check.</param>
|
|
///
|
|
/// <returns>a bool indicating whether the password matches.</returns>
|
|
public static bool CheckZipPassword(string zipFileName, string password)
|
|
{
|
|
// workitem 13664
|
|
bool success = false;
|
|
try
|
|
{
|
|
using (ZipFile zip1 = ZipFile.Read(zipFileName))
|
|
{
|
|
foreach (var e in zip1)
|
|
{
|
|
if (!e.IsDirectory && e.UsesEncryption)
|
|
{
|
|
e.ExtractWithPassword(System.IO.Stream.Null, password);
|
|
}
|
|
}
|
|
}
|
|
success = true;
|
|
}
|
|
catch(Ionic.Zip.BadPasswordException) { }
|
|
return success;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Provides a human-readable string with information about the ZipFile.
|
|
/// </summary>
|
|
///
|
|
/// <remarks>
|
|
/// <para>
|
|
/// The information string contains 10 lines or so, about each ZipEntry,
|
|
/// describing whether encryption is in use, the compressed and uncompressed
|
|
/// length of the entry, the offset of the entry, and so on. As a result the
|
|
/// information string can be very long for zip files that contain many
|
|
/// entries.
|
|
/// </para>
|
|
/// <para>
|
|
/// This information is mostly useful for diagnostic purposes.
|
|
/// </para>
|
|
/// </remarks>
|
|
public string Info
|
|
{
|
|
get
|
|
{
|
|
var builder = new System.Text.StringBuilder();
|
|
builder.Append(string.Format(" ZipFile: {0}\n", this.Name));
|
|
if (!string.IsNullOrEmpty(this._Comment))
|
|
{
|
|
builder.Append(string.Format(" Comment: {0}\n", this._Comment));
|
|
}
|
|
if (this._versionMadeBy != 0)
|
|
{
|
|
builder.Append(string.Format(" version made by: 0x{0:X4}\n", this._versionMadeBy));
|
|
}
|
|
if (this._versionNeededToExtract != 0)
|
|
{
|
|
builder.Append(string.Format("needed to extract: 0x{0:X4}\n", this._versionNeededToExtract));
|
|
}
|
|
|
|
builder.Append(string.Format(" uses ZIP64: {0}\n", this.InputUsesZip64));
|
|
|
|
builder.Append(string.Format(" disk with CD: {0}\n", this._diskNumberWithCd));
|
|
if (this._OffsetOfCentralDirectory == 0xFFFFFFFF)
|
|
builder.Append(string.Format(" CD64 offset: 0x{0:X16}\n", this._OffsetOfCentralDirectory64));
|
|
else
|
|
builder.Append(string.Format(" CD offset: 0x{0:X8}\n", this._OffsetOfCentralDirectory));
|
|
builder.Append("\n");
|
|
foreach (ZipEntry entry in this._entries.Values)
|
|
{
|
|
builder.Append(entry.Info);
|
|
}
|
|
return builder.ToString();
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
} |