Mes documents/Visual Studio 2005/Projects/TES4ModTranslator/TES4ModTranslator/Zip/ZipEntry.cs

Go to the documentation of this file.
00001 // ZipEntry.cs
00002 //
00003 // Copyright (C) 2001 Mike Krueger
00004 // Copyright (C) 2004 John Reilly
00005 //
00006 // This file was translated from java, it was part of the GNU Classpath
00007 // Copyright (C) 2001 Free Software Foundation, Inc.
00008 //
00009 // This program is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU General Public License
00011 // as published by the Free Software Foundation; either version 2
00012 // of the License, or (at your option) any later version.
00013 //
00014 // This program is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU General Public License
00020 // along with this program; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 //
00023 // Linking this library statically or dynamically with other modules is
00024 // making a combined work based on this library.  Thus, the terms and
00025 // conditions of the GNU General Public License cover the whole
00026 // combination.
00027 // 
00028 // As a special exception, the copyright holders of this library give you
00029 // permission to link this library with independent modules to produce an
00030 // executable, regardless of the license terms of these independent
00031 // modules, and to copy and distribute the resulting executable under
00032 // terms of your choice, provided that you also meet, for each linked
00033 // independent module, the terms and conditions of the license of that
00034 // module.  An independent module is a module which is not derived from
00035 // or based on this library.  If you modify this library, you may extend
00036 // this exception to your version of the library, but you are not
00037 // obligated to do so.  If you do not wish to do so, delete this
00038 // exception statement from your version.
00039 
00040 using System;
00041 using System.IO;
00042 
00043 namespace ICSharpCode.SharpZipLib.Zip
00044 {
00045         
00055         public class ZipEntry : ICloneable
00056         {
00057                 static int KNOWN_SIZE               = 1;
00058                 static int KNOWN_CSIZE              = 2;
00059                 static int KNOWN_CRC                = 4;
00060                 static int KNOWN_TIME               = 8;
00061                 static int KNOWN_EXTERN_ATTRIBUTES      = 16;
00062                 
00063                 ushort known = 0;                       // Bit flags made up of above bits
00064                 int    externalFileAttributes = -1;     // contains external attributes (os dependant)
00065                 
00066                 ushort versionMadeBy;                   // Contains host system and version information
00067                                                         // only relevant for central header entries
00068                 
00069                 string name;
00070                 ulong  size;
00071                 ulong  compressedSize;
00072                 ushort versionToExtract;                // Version required to extract (library handles <= 2.0)
00073                 uint   crc;
00074                 uint   dosTime;
00075                 
00076                 CompressionMethod  method = CompressionMethod.Deflated;
00077                 byte[] extra = null;
00078                 string comment = null;
00079                 
00080                 int flags;                             // general purpose bit flags
00081 
00082                 int zipFileIndex = -1;                 // used by ZipFile
00083                 int offset;                            // used by ZipFile and ZipOutputStream
00084                 
00089                 public bool IsCrypted {
00090                         get {
00091                                 return (flags & 1) != 0; 
00092                         }
00093                         set {
00094                                 if (value) {
00095                                         flags |= 1;
00096                                 } else {
00097                                         flags &= ~1;
00098                                 }
00099                         }
00100                 }
00101                 
00128                 public int Flags {
00129                         get { 
00130                                 return flags; 
00131                         }
00132                         set {
00133                                 flags = value; 
00134                         }
00135                 }
00136 
00137 
00141                 public int ZipFileIndex {
00142                         get {
00143                                 return zipFileIndex;
00144                         }
00145                         set {
00146                                 zipFileIndex = value;
00147                         }
00148                 }
00149                 
00153                 public int Offset {
00154                         get {
00155                                 return offset;
00156                         }
00157                         set {
00158                                 if (((ulong)value & 0xFFFFFFFF00000000L) != 0) {
00159                                         throw new ArgumentOutOfRangeException("Offset");
00160                                 }
00161                                 offset = value;
00162                         }
00163                 }
00164 
00165 
00171                 public int ExternalFileAttributes {
00172                         get {
00173                                 if ((known & KNOWN_EXTERN_ATTRIBUTES) == 0) {
00174                                         return -1;
00175                                 } else {
00176                                         return externalFileAttributes;
00177                                 }
00178                         }
00179                         
00180                         set {
00181                                 externalFileAttributes = value;
00182                                 known |= (ushort)KNOWN_EXTERN_ATTRIBUTES;
00183                         }
00184                 }
00185 
00191                 public int VersionMadeBy {
00192                         get { 
00193                                 return versionMadeBy & 0xff; 
00194                         }
00195                 }
00196 
00234 
00235                 public int HostSystem {
00236                         get { return (versionMadeBy >> 8) & 0xff; }
00237                 }
00238                 
00251                 public ZipEntry(string name) : this(name, 0, ZipConstants.VERSION_MADE_BY)
00252                 {
00253                 }
00254 
00270                 internal ZipEntry(string name, int versionRequiredToExtract) : this(name, versionRequiredToExtract, ZipConstants.VERSION_MADE_BY)
00271                 {
00272                 }
00273                 
00290                 internal ZipEntry(string name, int versionRequiredToExtract, int madeByInfo)
00291                 {
00292                         if (name == null)  {
00293                                 throw new System.ArgumentNullException("ZipEntry name");
00294                         }
00295 
00296                         if ( name.Length == 0 ) {
00297                                 throw new ArgumentException("ZipEntry name is empty");
00298                         }
00299 
00300                         if (versionRequiredToExtract != 0 && versionRequiredToExtract < 10) {
00301                                 throw new ArgumentOutOfRangeException("versionRequiredToExtract");
00302                         }
00303                         
00304                         this.DateTime         = System.DateTime.Now;
00305                         this.name             = name;
00306                         this.versionMadeBy    = (ushort)madeByInfo;
00307                         this.versionToExtract = (ushort)versionRequiredToExtract;
00308                 }
00309                 
00316                 public ZipEntry(ZipEntry e)
00317                 {
00318                         known                  = e.known;
00319                         name                   = e.name;
00320                         size                   = e.size;
00321                         compressedSize         = e.compressedSize;
00322                         crc                    = e.crc;
00323                         dosTime                = e.dosTime;
00324                         method                 = e.method;
00325                         ExtraData              = e.ExtraData;     // Note use of property ensuring data is unique
00326                         comment                = e.comment;
00327                         versionToExtract       = e.versionToExtract;
00328                         versionMadeBy          = e.versionMadeBy;
00329                         externalFileAttributes = e.externalFileAttributes;
00330                         flags                  = e.flags;
00331 
00332                         zipFileIndex           = -1;
00333                         offset                 = 0;
00334                 }
00335 
00361                 public int Version {
00362                         get {
00363                                 if (versionToExtract != 0) {
00364                                         return versionToExtract;
00365                                 } else {
00366                                         int result = 10;
00367                                         if (CompressionMethod.Deflated == method) {
00368                                                 result = 20;
00369                                         } else if (IsDirectory == true) {
00370                                                 result = 20;
00371                                         } else if (IsCrypted == true) {
00372                                                 result = 20;
00373                                         } else if ((known & KNOWN_EXTERN_ATTRIBUTES) != 0 && (externalFileAttributes & 0x08) != 0) {
00374                                                 result = 11;
00375                                         }
00376                                         return result;
00377                                 }
00378                         }
00379                 }
00380 
00384                 public bool RequiresZip64 {
00385                         get {
00386                                 return (this.size > uint.MaxValue) || (this.compressedSize > uint.MaxValue);
00387                         }
00388                 }
00389                 
00393                 public long DosTime {
00394                         get {
00395                                 if ((known & KNOWN_TIME) == 0) {
00396                                         return 0;
00397                                 } else {
00398                                         return dosTime;
00399                                 }
00400                         }
00401                         set {
00402                                 this.dosTime = (uint)value;
00403                                 known |= (ushort)KNOWN_TIME;
00404                         }
00405                 }
00406                 
00407                 
00411                 public DateTime DateTime {
00412                         get {
00413                                 // Although technically not valid some archives have dates set to zero.
00414                                 // This mimics some archivers handling and is a good a cludge as any probably.
00415                                 if ( dosTime == 0 ) {
00416                                         return DateTime.Now;
00417                                 }
00418                                 else {
00419                                         uint sec  = 2 * (dosTime & 0x1f);
00420                                         uint min  = (dosTime >> 5) & 0x3f;
00421                                         uint hrs  = (dosTime >> 11) & 0x1f;
00422                                         uint day  = (dosTime >> 16) & 0x1f;
00423                                         uint mon  = ((dosTime >> 21) & 0xf);
00424                                         uint year = ((dosTime >> 25) & 0x7f) + 1980;
00425                                         return new System.DateTime((int)year, (int)mon, (int)day, (int)hrs, (int)min, (int)sec);
00426                                 }
00427                         }
00428                         set {
00429                                 DosTime = ((uint)value.Year - 1980 & 0x7f) << 25 | 
00430                                           ((uint)value.Month) << 21 |
00431                                           ((uint)value.Day) << 16 |
00432                                           ((uint)value.Hour) << 11 |
00433                                           ((uint)value.Minute) << 5 |
00434                                           ((uint)value.Second) >> 1;
00435                         }
00436                 }
00437                 
00443                 public string Name {
00444                         get {
00445                                 return name;
00446                         }
00447                 }
00448                 
00456                 static public string CleanName(string name, bool relativePath)
00457                 {
00458                         if (name == null) {
00459                                 return "";
00460                         }
00461                         
00462                         if (Path.IsPathRooted(name) == true) {
00463                                 // NOTE:
00464                                 // for UNC names...  \\machine\share\zoom\beet.txt gives \zoom\beet.txt
00465                                 name = name.Substring(Path.GetPathRoot(name).Length);
00466                         }
00467 
00468                         name = name.Replace(@"\", "/");
00469                         
00470                         if (relativePath == true) {
00471                                 if (name.Length > 0 && (name[0] == Path.AltDirectorySeparatorChar || name[0] == Path.DirectorySeparatorChar)) {
00472                                         name = name.Remove(0, 1);
00473                                 }
00474                         } else {
00475                                 if (name.Length > 0 && name[0] != Path.AltDirectorySeparatorChar && name[0] != Path.DirectorySeparatorChar) {
00476                                         name = name.Insert(0, "/");
00477                                 }
00478                         }
00479                         return name;
00480                 }
00481                 
00490                 static public string CleanName(string name)
00491                 {
00492                         return CleanName(name, true);
00493                 }
00494                 
00504                 public long Size {
00505                         get {
00506                                 return (known & KNOWN_SIZE) != 0 ? (long)size : -1L;
00507                         }
00508                         set {
00509                                 if (((ulong)value & 0xFFFFFFFF00000000L) != 0) {
00510                                         throw new ArgumentOutOfRangeException("size");
00511                                 }
00512                                 this.size  = (ulong)value;
00513                                 this.known |= (ushort)KNOWN_SIZE;
00514                         }
00515                 }
00516                 
00526                 public long CompressedSize {
00527                         get {
00528                                 return (known & KNOWN_CSIZE) != 0 ? (long)compressedSize : -1L;
00529                         }
00530                         set {
00531                                 if (((ulong)value & 0xffffffff00000000L) != 0) {
00532                                         throw new ArgumentOutOfRangeException();
00533                                 }
00534                                 this.compressedSize = (ulong)value;
00535                                 this.known |= (ushort)KNOWN_CSIZE;
00536                         }
00537                 }
00538                 
00548                 public long Crc {
00549                         get {
00550                                 return (known & KNOWN_CRC) != 0 ? crc & 0xffffffffL : -1L;
00551                         }
00552                         set {
00553                                 if (((ulong)crc & 0xffffffff00000000L) != 0) {
00554                                         throw new ArgumentOutOfRangeException();
00555                                 }
00556                                 this.crc = (uint)value;
00557                                 this.known |= (ushort)KNOWN_CRC;
00558                         }
00559                 }
00560                 
00569                 public CompressionMethod CompressionMethod {
00570                         get {
00571                                 return method;
00572                         }
00573                         set {
00574                                 this.method = value;
00575                         }
00576                 }
00577                 
00587                 public byte[] ExtraData {
00588                         get {
00589                                 return extra;
00590                         }
00591                         set {
00592                                 if (value == null) {
00593                                         this.extra = null;
00594                                         return;
00595                                 }
00596                                 
00597                                 if (value.Length > 0xffff) {
00598                                         throw new System.ArgumentOutOfRangeException();
00599                                 }
00600                                 
00601                                 this.extra = new byte[value.Length];
00602                                 Array.Copy(value, 0, this.extra, 0, value.Length);
00603                                 
00604                                 try {
00605                                         int pos = 0;
00606                                         while (pos < extra.Length) {
00607                                                 int sig = (extra[pos++] & 0xff) | (extra[pos++] & 0xff) << 8;
00608                                                 int len = (extra[pos++] & 0xff) | (extra[pos++] & 0xff) << 8;
00609                                                 
00610                                                 if (len < 0 || pos + len > extra.Length) {
00611                                                         // This is still lenient but the extra data is corrupt
00612                                                         // TODO: drop the extra data? or somehow indicate to user 
00613                                                         // there is a problem...
00614                                                         break;
00615                                                 }
00616                                                 
00617                                                 if (sig == 0x5455) {
00618                                                         // extended time stamp, unix format by Rainer Prem <Rainer@Prem.de>
00619                                                         int flags = extra[pos];
00620                                                         // Can include other times but these are ignored.  Length of data should
00621                                                         // actually be 1 + 4 * no of bits in flags.
00622                                                         if ((flags & 1) != 0 && len >= 5) {
00623                                                                 int iTime = ((extra[pos+1] & 0xff) |
00624                                                                         (extra[pos + 2] & 0xff) << 8 |
00625                                                                         (extra[pos + 3] & 0xff) << 16 |
00626                                                                         (extra[pos + 4] & 0xff) << 24);
00627                                                                 
00628                                                                 DateTime = (new DateTime ( 1970, 1, 1, 0, 0, 0 ) + new TimeSpan ( 0, 0, 0, iTime, 0 )).ToLocalTime ();
00629                                                                 known |= (ushort)KNOWN_TIME;
00630                                                         }
00631                                                 } else if (sig == 0x0001) { 
00632                                                         // ZIP64 extended information extra field
00633                                                         // Of variable size depending on which fields in header are too small
00634                                                         // fields appear here if the corresponding local or central directory record field
00635                                                         // is set to 0xFFFF or 0xFFFFFFFF and the entry is in Zip64 format.
00636                                                         //
00637                                                         // Original Size          8 bytes
00638                                                         // Compressed size        8 bytes
00639                                                         // Relative header offset 8 bytes
00640                                                         // Disk start number      4 bytes
00641                                                 }
00642                                                 pos += len;
00643                                         }
00644                                 } catch (Exception) {
00645                                         /* be lenient */
00646                                         return;
00647                                 }
00648                         }
00649                 }
00650                 
00651                 
00661                 public string Comment {
00662                         get {
00663                                 return comment;
00664                         }
00665                         set {
00666                                 // TODO: this test is strictly incorrect as the length is in characters
00667                                 // While the test is correct in that a comment of this length or greater 
00668                                 // is definitely invalid, shorter comments may also have an invalid length.
00669                                 if (value != null && value.Length > 0xffff) {
00670                                         throw new ArgumentOutOfRangeException();
00671                                 }
00672                                 this.comment = value;
00673                         }
00674                 }
00675                 
00682                 public bool IsDirectory {
00683                         get {
00684                                 int nlen = name.Length;
00685                                 bool result = nlen > 0 && name[nlen - 1] == '/';
00686                                 
00687                                 if (result == false && (known & KNOWN_EXTERN_ATTRIBUTES) != 0) {
00688                                         if (HostSystem == 0 && (ExternalFileAttributes & 16) != 0) {
00689                                                 result = true;
00690                                         }
00691                                 }
00692                                 return result;
00693                         }
00694                 }
00695                 
00703                 public bool IsFile {
00704                         get {
00705                                 bool result = !IsDirectory;
00706 
00707                                 // Exclude volume labels
00708                                 if ( result && (known & KNOWN_EXTERN_ATTRIBUTES) != 0) {
00709                                         if (HostSystem == 0 && (ExternalFileAttributes & 8) != 0) {
00710                                                 result = false;
00711                                         }
00712                                 }
00713                                 return result;
00714                         }
00715                 }
00716                 
00720                 public object Clone()
00721                 {
00722                         return this.MemberwiseClone();
00723                 }
00724                 
00728                 public override string ToString()
00729                 {
00730                         return name;
00731                 }
00732         }
00733 }

Generated on Fri Jun 23 21:50:05 2006 for OblivionModTranslator by  doxygen 1.4.6-NO