📄 zipentry.cs
字号:
result = 20;
} else if (IsDirectory == true) {
result = 20;
} else if (IsCrypted == true) {
result = 20;
} else if ((known & KNOWN_EXTERN_ATTRIBUTES) != 0 && (externalFileAttributes & 0x08) != 0) {
result = 11;
}
return result;
}
}
}
/// <summary>
/// Gets a value indicating if the entry requires Zip64 extensions to be stored
/// </summary>
public bool RequiresZip64 {
get {
return (this.size > uint.MaxValue) || (this.compressedSize > uint.MaxValue);
}
}
/// <summary>
/// Get/Set DosTime
/// </summary>
public long DosTime {
get {
if ((known & KNOWN_TIME) == 0) {
return 0;
} else {
return dosTime;
}
}
set {
this.dosTime = (uint)value;
known |= (ushort)KNOWN_TIME;
}
}
/// <summary>
/// Gets/Sets the time of last modification of the entry.
/// </summary>
public DateTime DateTime {
get {
// Although technically not valid some archives have dates set to zero.
// This mimics some archivers handling and is a good a cludge as any probably.
if ( dosTime == 0 ) {
return DateTime.Now;
}
else {
uint sec = 2 * (dosTime & 0x1f);
uint min = (dosTime >> 5) & 0x3f;
uint hrs = (dosTime >> 11) & 0x1f;
uint day = (dosTime >> 16) & 0x1f;
uint mon = ((dosTime >> 21) & 0xf);
uint year = ((dosTime >> 25) & 0x7f) + 1980;
return new System.DateTime((int)year, (int)mon, (int)day, (int)hrs, (int)min, (int)sec);
}
}
set {
DosTime = ((uint)value.Year - 1980 & 0x7f) << 25 |
((uint)value.Month) << 21 |
((uint)value.Day) << 16 |
((uint)value.Hour) << 11 |
((uint)value.Minute) << 5 |
((uint)value.Second) >> 1;
}
}
/// <summary>
/// Returns the entry name. The path components in the entry should
/// always separated by slashes ('/'). Dos device names like C: should also
/// be removed. See <see cref="CleanName">CleanName</see>.
/// </summary>
public string Name {
get {
return name;
}
}
/// <summary>
/// Cleans a name making it conform to Zip file conventions.
/// Devices names ('c:\') and UNC share names ('\\server\share') are removed
/// and forward slashes ('\') are converted to back slashes ('/').
/// </summary>
/// <param name="name">Name to clean</param>
/// <param name="relativePath">Make names relative if true or absolute if false</param>
static public string CleanName(string name, bool relativePath)
{
if (name == null) {
return "";
}
if (Path.IsPathRooted(name) == true) {
// NOTE:
// for UNC names... \\machine\share\zoom\beet.txt gives \zoom\beet.txt
name = name.Substring(Path.GetPathRoot(name).Length);
}
name = name.Replace(@"\", "/");
if (relativePath == true) {
if (name.Length > 0 && (name[0] == Path.AltDirectorySeparatorChar || name[0] == Path.DirectorySeparatorChar)) {
name = name.Remove(0, 1);
}
} else {
if (name.Length > 0 && name[0] != Path.AltDirectorySeparatorChar && name[0] != Path.DirectorySeparatorChar) {
name = name.Insert(0, "/");
}
}
return name;
}
/// <summary>
/// Cleans a name making it conform to Zip file conventions.
/// Devices names ('c:\') and UNC share names ('\\server\share') are removed
/// and forward slashes ('\') are converted to back slashes ('/').
/// Names are made relative by trimming leading slashes which is compatible
/// with Windows-XPs built in Zip file handling.
/// </summary>
/// <param name="name">Name to clean</param>
static public string CleanName(string name)
{
return CleanName(name, true);
}
/// <summary>
/// Gets/Sets the size of the uncompressed data.
/// </summary>
/// <exception cref="System.ArgumentOutOfRangeException">
/// If the size is not in the range 0..0xffffffffL
/// </exception>
/// <returns>
/// The size or -1 if unknown.
/// </returns>
public long Size {
get {
return (known & KNOWN_SIZE) != 0 ? (long)size : -1L;
}
set {
if (((ulong)value & 0xFFFFFFFF00000000L) != 0) {
throw new ArgumentOutOfRangeException("size");
}
this.size = (ulong)value;
this.known |= (ushort)KNOWN_SIZE;
}
}
/// <summary>
/// Gets/Sets the size of the compressed data.
/// </summary>
/// <exception cref="System.ArgumentOutOfRangeException">
/// Size is not in the range 0..0xffffffff
/// </exception>
/// <returns>
/// The size or -1 if unknown.
/// </returns>
public long CompressedSize {
get {
return (known & KNOWN_CSIZE) != 0 ? (long)compressedSize : -1L;
}
set {
if (((ulong)value & 0xffffffff00000000L) != 0) {
throw new ArgumentOutOfRangeException();
}
this.compressedSize = (ulong)value;
this.known |= (ushort)KNOWN_CSIZE;
}
}
/// <summary>
/// Gets/Sets the crc of the uncompressed data.
/// </summary>
/// <exception cref="System.ArgumentOutOfRangeException">
/// Crc is not in the range 0..0xffffffffL
/// </exception>
/// <returns>
/// The crc value or -1 if unknown.
/// </returns>
public long Crc {
get {
return (known & KNOWN_CRC) != 0 ? crc & 0xffffffffL : -1L;
}
set {
if (((ulong)crc & 0xffffffff00000000L) != 0) {
throw new ArgumentOutOfRangeException();
}
this.crc = (uint)value;
this.known |= (ushort)KNOWN_CRC;
}
}
/// <summary>
/// Gets/Sets the compression method. Only Deflated and Stored are supported.
/// </summary>
/// <returns>
/// The compression method for this entry
/// </returns>
/// <see cref="ICSharpCode.SharpZipLib.Zip.CompressionMethod.Deflated"/>
/// <see cref="ICSharpCode.SharpZipLib.Zip.CompressionMethod.Stored"/>
public CompressionMethod CompressionMethod {
get {
return method;
}
set {
this.method = value;
}
}
/// <summary>
/// Gets/Sets the extra data.
/// </summary>
/// <exception cref="System.ArgumentOutOfRangeException">
/// Extra data is longer than 0xffff bytes.
/// </exception>
/// <returns>
/// Extra data or null if not set.
/// </returns>
public byte[] ExtraData {
get {
return extra;
}
set {
if (value == null) {
this.extra = null;
return;
}
if (value.Length > 0xffff) {
throw new System.ArgumentOutOfRangeException();
}
this.extra = new byte[value.Length];
Array.Copy(value, 0, this.extra, 0, value.Length);
try {
int pos = 0;
while (pos < extra.Length) {
int sig = (extra[pos++] & 0xff) | (extra[pos++] & 0xff) << 8;
int len = (extra[pos++] & 0xff) | (extra[pos++] & 0xff) << 8;
if (len < 0 || pos + len > extra.Length) {
// This is still lenient but the extra data is corrupt
// TODO: drop the extra data? or somehow indicate to user
// there is a problem...
break;
}
if (sig == 0x5455) {
// extended time stamp, unix format by Rainer Prem <Rainer@Prem.de>
int flags = extra[pos];
// Can include other times but these are ignored. Length of data should
// actually be 1 + 4 * no of bits in flags.
if ((flags & 1) != 0 && len >= 5) {
int iTime = ((extra[pos+1] & 0xff) |
(extra[pos + 2] & 0xff) << 8 |
(extra[pos + 3] & 0xff) << 16 |
(extra[pos + 4] & 0xff) << 24);
DateTime = (new DateTime ( 1970, 1, 1, 0, 0, 0 ) + new TimeSpan ( 0, 0, 0, iTime, 0 )).ToLocalTime ();
known |= (ushort)KNOWN_TIME;
}
} else if (sig == 0x0001) {
// ZIP64 extended information extra field
// Of variable size depending on which fields in header are too small
// fields appear here if the corresponding local or central directory record field
// is set to 0xFFFF or 0xFFFFFFFF and the entry is in Zip64 format.
//
// Original Size 8 bytes
// Compressed size 8 bytes
// Relative header offset 8 bytes
// Disk start number 4 bytes
}
pos += len;
}
} catch (Exception) {
/* be lenient */
return;
}
}
}
/// <summary>
/// Gets/Sets the entry comment.
/// </summary>
/// <exception cref="System.ArgumentOutOfRangeException">
/// If comment is longer than 0xffff.
/// </exception>
/// <returns>
/// The comment or null if not set.
/// </returns>
public string Comment {
get {
return comment;
}
set {
// TODO: this test is strictly incorrect as the length is in characters
// While the test is correct in that a comment of this length or greater
// is definitely invalid, shorter comments may also have an invalid length.
if (value != null && value.Length > 0xffff) {
throw new ArgumentOutOfRangeException();
}
this.comment = value;
}
}
/// <summary>
/// Gets a value indicating of the if the entry is a directory. A directory is determined by
/// an entry name with a trailing slash '/'. The external file attributes
/// can also mark a file as a directory. The trailing slash convention should always be followed
/// however.
/// </summary>
public bool IsDirectory {
get {
int nlen = name.Length;
bool result = nlen > 0 && name[nlen - 1] == '/';
if (result == false && (known & KNOWN_EXTERN_ATTRIBUTES) != 0) {
if (HostSystem == 0 && (ExternalFileAttributes & 16) != 0) {
result = true;
}
}
return result;
}
}
/// <summary>
/// Get a value of true if the entry appears to be a file; false otherwise
/// </summary>
/// <remarks>
/// This only takes account Windows attributes. Other operating systems are ignored.
/// For linux and others the result may be incorrect.
/// </remarks>
public bool IsFile {
get {
bool result = !IsDirectory;
// Exclude volume labels
if ( result && (known & KNOWN_EXTERN_ATTRIBUTES) != 0) {
if (HostSystem == 0 && (ExternalFileAttributes & 8) != 0) {
result = false;
}
}
return result;
}
}
/// <summary>
/// Creates a copy of this zip entry.
/// </summary>
public object Clone()
{
return this.MemberwiseClone();
}
/// <summary>
/// Gets the string representation of this ZipEntry.
/// </summary>
public override string ToString()
{
return name;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -