From 1d52d1eaddaf740479bc574c9809c17bc275db0c Mon Sep 17 00:00:00 2001 From: BruceChen Date: Sun, 2 Oct 2022 18:31:08 +0800 Subject: [PATCH] Fix all warnings & Trim (#2226) * Fix AutoFishing crash * Fix all warnings * Remove DotNetZip. * Fix the usage of HttpClient. --- MinecraftClient/AutoTimeout.cs | 9 +- MinecraftClient/ChatBots/Alerts.cs | 8 +- MinecraftClient/ChatBots/AntiAFK.cs | 13 +- MinecraftClient/ChatBots/AutoAttack.cs | 42 +- MinecraftClient/ChatBots/AutoCraft.cs | 109 +- MinecraftClient/ChatBots/AutoDrop.cs | 33 +- MinecraftClient/ChatBots/AutoEat.cs | 6 +- MinecraftClient/ChatBots/AutoFishing.cs | 5 +- MinecraftClient/ChatBots/AutoRelog.cs | 16 +- MinecraftClient/ChatBots/AutoRespond.cs | 68 +- MinecraftClient/ChatBots/BotsCommand.cs | 8 +- MinecraftClient/ChatBots/ChatLog.cs | 53 +- MinecraftClient/ChatBots/FollowPlayer.cs | 14 +- MinecraftClient/ChatBots/HangmanGame.cs | 31 +- MinecraftClient/ChatBots/Mailer.cs | 74 +- MinecraftClient/ChatBots/Map.cs | 39 +- MinecraftClient/ChatBots/PlayerListLogger.cs | 26 +- MinecraftClient/ChatBots/Reload.cs | 6 +- MinecraftClient/ChatBots/RemoteControl.cs | 5 +- MinecraftClient/ChatBots/ReplayCapture.cs | 17 +- MinecraftClient/ChatBots/Script.cs | 47 +- MinecraftClient/ChatBots/ScriptScheduler.cs | 54 +- MinecraftClient/ChatBots/TestBot.cs | 7 +- MinecraftClient/Command.cs | 34 +- MinecraftClient/Commands/Animation.cs | 11 +- MinecraftClient/Commands/Bed.cs | 4 +- MinecraftClient/Commands/ChangeSlot.cs | 12 +- MinecraftClient/Commands/Chunk.cs | 31 +- MinecraftClient/Commands/Connect.cs | 11 +- MinecraftClient/Commands/Debug.cs | 11 +- MinecraftClient/Commands/Dig.cs | 6 +- MinecraftClient/Commands/DropItem.cs | 10 +- MinecraftClient/Commands/Entitycmd.cs | 27 +- MinecraftClient/Commands/ExecIf.cs | 71 +- MinecraftClient/Commands/ExecMulti.cs | 13 +- MinecraftClient/Commands/Exit.cs | 9 +- MinecraftClient/Commands/Health.cs | 5 +- MinecraftClient/Commands/Inventory.cs | 6 +- MinecraftClient/Commands/List.cs | 4 +- MinecraftClient/Commands/Log.cs | 11 +- MinecraftClient/Commands/Look.cs | 13 +- MinecraftClient/Commands/Move.cs | 24 +- MinecraftClient/Commands/Reco.cs | 9 +- MinecraftClient/Commands/Respawn.cs | 7 +- MinecraftClient/Commands/Script.cs | 11 +- MinecraftClient/Commands/Send.cs | 11 +- MinecraftClient/Commands/Set.cs | 13 +- MinecraftClient/Commands/SetRnd.cs | 25 +- MinecraftClient/Commands/Sneak.cs | 10 +- MinecraftClient/Commands/Tps.cs | 7 +- MinecraftClient/Commands/UseItem.cs | 7 +- MinecraftClient/Commands/Useblock.cs | 9 +- MinecraftClient/ConsoleIO.cs | 23 +- MinecraftClient/Crypto/AesCfb8Stream.cs | 13 +- MinecraftClient/Crypto/CryptoHandler.cs | 41 +- MinecraftClient/FileMonitor.cs | 22 +- MinecraftClient/INIFile.cs | 17 +- MinecraftClient/Inventory/Container.cs | 70 +- MinecraftClient/Inventory/ContainerType.cs | 39 +- .../Inventory/ContainerTypeExtensions.cs | 114 +- MinecraftClient/Inventory/Effects.cs | 6 - MinecraftClient/Inventory/Item.cs | 52 +- MinecraftClient/Inventory/ItemMovingHelper.cs | 24 +- .../Inventory/ItemPalettes/ItemPalette.cs | 7 +- .../Inventory/ItemPalettes/ItemPalette115.cs | 3 +- .../Inventory/ItemPalettes/ItemPalette1161.cs | 3 +- .../Inventory/ItemPalettes/ItemPalette1162.cs | 3 +- .../Inventory/ItemPalettes/ItemPalette117.cs | 3 +- .../Inventory/ItemPalettes/ItemPalette118.cs | 3 +- .../Inventory/ItemPalettes/ItemPalette119.cs | 3 +- .../ItemPalettes/ItemPaletteGenerator.cs | 8 +- .../Inventory/ItemTypeExtensions.cs | 2 - MinecraftClient/Inventory/VillagerTrade.cs | 24 +- MinecraftClient/Inventory/WindowActionType.cs | 7 +- MinecraftClient/Json.cs | 18 +- MinecraftClient/Logger/FileLogLogger.cs | 15 +- MinecraftClient/Logger/FilteredLogger.cs | 10 +- MinecraftClient/Logger/ILogger.cs | 7 +- MinecraftClient/Logger/LoggerBase.cs | 19 +- MinecraftClient/Mapping/Block.cs | 17 +- .../Mapping/BlockPalettes/BlockPalette.cs | 5 +- .../BlockPalettes/BlockPaletteGenerator.cs | 21 +- .../Mapping/BlockPalettes/Palette112.cs | 3 +- .../Mapping/BlockPalettes/Palette113.cs | 3 +- .../Mapping/BlockPalettes/Palette114.cs | 3 +- .../Mapping/BlockPalettes/Palette115.cs | 3 +- .../Mapping/BlockPalettes/Palette116.cs | 3 +- .../Mapping/BlockPalettes/Palette117.cs | 3 +- .../Mapping/BlockPalettes/Palette119.cs | 3 +- MinecraftClient/Mapping/Chunk.cs | 4 - MinecraftClient/Mapping/ChunkColumn.cs | 4 - MinecraftClient/Mapping/CommandBlockFlags.cs | 5 - MinecraftClient/Mapping/CommandBlockMode.cs | 5 - MinecraftClient/Mapping/Dimension.cs | 68 +- MinecraftClient/Mapping/Direction.cs | 7 +- MinecraftClient/Mapping/Entity.cs | 62 +- .../Mapping/EntityPalettes/EntityPalette.cs | 9 +- .../EntityPalettes/EntityPalette112.cs | 3 +- .../EntityPalettes/EntityPalette113.cs | 1 - .../EntityPalettes/EntityPalette114.cs | 3 +- .../EntityPalettes/EntityPalette115.cs | 3 +- .../EntityPalettes/EntityPalette1161.cs | 3 +- .../EntityPalettes/EntityPalette1162.cs | 3 +- .../EntityPalettes/EntityPalette117.cs | 3 +- .../EntityPalettes/EntityPalette119.cs | 3 +- .../Mapping/EntityTypeExtensions.cs | 7 +- MinecraftClient/Mapping/InteractType.cs | 8 +- MinecraftClient/Mapping/Location.cs | 27 +- MinecraftClient/Mapping/MapIcon.cs | 9 +- MinecraftClient/Mapping/MapIconType.cs | 8 +- MinecraftClient/Mapping/Material2Tool.cs | 28 +- MinecraftClient/Mapping/MaterialExtensions.cs | 6 +- MinecraftClient/Mapping/Movement.cs | 42 +- MinecraftClient/Mapping/World.cs | 35 +- MinecraftClient/McClient.cs | 217 +- MinecraftClient/MinecraftClient.csproj | 19 +- MinecraftClient/Program.cs | 93 +- MinecraftClient/Properties/AssemblyInfo.cs | 1 - MinecraftClient/Protocol/DataTypeGenerator.cs | 21 +- MinecraftClient/Protocol/EntityActionType.cs | 5 - MinecraftClient/Protocol/GuidExtensions.cs | 3 - .../Protocol/Handlers/Compression/CRC32.cs | 814 ---- .../Protocol/Handlers/Compression/Deflate.cs | 1879 -------- .../Handlers/Compression/DeflateStream.cs | 740 ---- .../Handlers/Compression/GZipStream.cs | 1033 ----- .../Protocol/Handlers/Compression/InfTree.cs | 436 -- .../Protocol/Handlers/Compression/Inflate.cs | 1797 -------- .../ParallelDeflateOutputStream.cs | 1386 ------ .../Protocol/Handlers/Compression/Tree.cs | 423 -- .../Handlers/Compression/Zip/ComHelper.cs | 116 - .../Compression/Zip/EncryptionAlgorithm.cs | 135 - .../Handlers/Compression/Zip/Events.cs | 684 --- .../Handlers/Compression/Zip/Exceptions.cs | 300 -- .../Zip/ExtractExistingFileAction.cs | 85 - .../Handlers/Compression/Zip/FileSelector.cs | 1608 ------- .../Handlers/Compression/Zip/OffsetStream.cs | 114 - .../Handlers/Compression/Zip/Shared.cs | 901 ---- .../Handlers/Compression/Zip/WinZipAes.cs | 941 ---- .../Handlers/Compression/Zip/ZipConstants.cs | 51 - .../Handlers/Compression/Zip/ZipCrypto.cs | 455 -- .../Handlers/Compression/Zip/ZipDirEntry.cs | 381 -- .../Compression/Zip/ZipEntry.Extract.cs | 1456 ------ .../Handlers/Compression/Zip/ZipEntry.Read.cs | 798 ---- .../Compression/Zip/ZipEntry.Write.cs | 2582 ----------- .../Handlers/Compression/Zip/ZipEntry.cs | 2968 ------------- .../Compression/Zip/ZipEntrySource.cs | 69 - .../Compression/Zip/ZipErrorAction.cs | 97 - .../Compression/Zip/ZipFile.AddUpdate.cs | 2182 --------- .../Handlers/Compression/Zip/ZipFile.Check.cs | 352 -- .../Compression/Zip/ZipFile.Events.cs | 1219 ----- .../Compression/Zip/ZipFile.Extract.cs | 298 -- .../Handlers/Compression/Zip/ZipFile.Read.cs | 1110 ----- .../Handlers/Compression/Zip/ZipFile.Save.cs | 964 ---- .../Zip/ZipFile.SaveSelfExtractor.cs | 1101 ----- .../Compression/Zip/ZipFile.Selector.cs | 1464 ------ .../Handlers/Compression/Zip/ZipFile.cs | 3910 ----------------- .../Compression/Zip/ZipFile.x-IEnumerable.cs | 154 - .../Compression/Zip/ZipInputStream.cs | 827 ---- .../Compression/Zip/ZipOutputStream.cs | 1817 -------- .../Compression/Zip/ZipSegmentedStream.cs | 571 --- .../Protocol/Handlers/Compression/Zlib.cs | 548 --- .../Handlers/Compression/ZlibBaseStream.cs | 627 --- .../Handlers/Compression/ZlibCodec.cs | 718 --- .../Handlers/Compression/ZlibConstants.cs | 127 - .../Handlers/Compression/ZlibStream.cs | 726 --- .../Protocol/Handlers/DataTypes.cs | 92 +- .../Handlers/Forge/FMLHandshakeClientState.cs | 7 +- .../Forge/FMLHandshakeDiscriminator.cs | 7 +- .../Protocol/Handlers/Forge/FMLVersion.cs | 7 +- .../Protocol/Handlers/Forge/ForgeInfo.cs | 18 +- .../PacketPalettes/PacketPalette110.cs | 7 +- .../PacketPalettes/PacketPalette112.cs | 7 +- .../PacketPalettes/PacketPalette1122.cs | 7 +- .../PacketPalettes/PacketPalette113.cs | 7 +- .../PacketPalettes/PacketPalette114.cs | 7 +- .../PacketPalettes/PacketPalette115.cs | 7 +- .../PacketPalettes/PacketPalette116.cs | 7 +- .../PacketPalettes/PacketPalette1162.cs | 7 +- .../PacketPalettes/PacketPalette117.cs | 4 +- .../PacketPalettes/PacketPalette118.cs | 4 +- .../PacketPalettes/PacketPalette119.cs | 4 +- .../PacketPalettes/PacketPalette1192.cs | 4 +- .../PacketPalettes/PacketPalette17.cs | 7 +- .../PacketPalettes/PacketPaletteHelper.cs | 44 +- .../PacketPalettes/PacketTypePalette.cs | 20 +- .../Protocol/Handlers/PacketType18Handler.cs | 12 +- .../Protocol/Handlers/PacketTypesIn.cs | 7 +- .../Protocol/Handlers/PacketTypesOut.cs | 7 +- .../Protocol/Handlers/Protocol16.cs | 365 +- .../Protocol/Handlers/Protocol18.cs | 256 +- .../Protocol/Handlers/Protocol18Forge.cs | 32 +- .../Protocol/Handlers/Protocol18Terrain.cs | 24 +- .../Protocol/Handlers/SocketWrapper.cs | 24 +- .../Protocol/Handlers/ZlibUtils.cs | 27 +- MinecraftClient/Protocol/IMinecraftCom.cs | 5 +- .../Protocol/IMinecraftComHandler.cs | 8 +- MinecraftClient/Protocol/JwtPayloadDecode.cs | 4 +- .../Protocol/Message/ChatMessage.cs | 14 +- .../Protocol/Message/ChatParser.cs | 93 +- .../Protocol/Message/LastSeenMessageList.cs | 7 +- .../Protocol/MicrosoftAuthentication.cs | 71 +- MinecraftClient/Protocol/MojangAPI.cs | 73 +- MinecraftClient/Protocol/PlayerInfo.cs | 23 +- .../Protocol/ProfileKey/KeyUtils.cs | 3 - .../Protocol/ProfileKey/KeysCache.cs | 20 +- .../Protocol/ProfileKey/PlayerKeyPair.cs | 10 +- .../Protocol/ProfileKey/PrivateKey.cs | 14 +- .../Protocol/ProfileKey/PublicKey.cs | 22 +- MinecraftClient/Protocol/ProtocolHandler.cs | 77 +- MinecraftClient/Protocol/ProxiedWebRequest.cs | 88 +- MinecraftClient/Protocol/ReplayHandler.cs | 115 +- .../Protocol/Session/SessionCache.cs | 47 +- .../Protocol/Session/SessionToken.cs | 32 +- MinecraftClient/Proxy/ProxyHandler.cs | 6 +- .../Resources/config/MinecraftClient.ini | 7 +- MinecraftClient/Scripting/CSharpRunner.cs | 86 +- MinecraftClient/Scripting/ChatBot.cs | 132 +- .../DynamicRun/Builder/CompileRunner.cs | 22 +- .../Scripting/DynamicRun/Builder/Compiler.cs | 85 +- .../SimpleUnloadableAssemblyLoadContext.cs | 2 +- MinecraftClient/Settings.cs | 68 +- MinecraftClient/TaskWithDelay.cs | 7 +- MinecraftClient/TaskWithResult.cs | 24 +- MinecraftClient/Translations.cs | 30 +- MinecraftClient/WinAPI/ConsoleIcon.cs | 75 +- MinecraftClient/WinAPI/ExitCleanUp.cs | 12 +- MinecraftClient/WinAPI/WindowsVersion.cs | 44 +- 227 files changed, 2201 insertions(+), 43564 deletions(-) delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/CRC32.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Deflate.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/DeflateStream.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/GZipStream.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/InfTree.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Inflate.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/ParallelDeflateOutputStream.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Tree.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ComHelper.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/EncryptionAlgorithm.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/Events.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/Exceptions.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ExtractExistingFileAction.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/FileSelector.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/OffsetStream.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/Shared.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/WinZipAes.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipConstants.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipCrypto.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipDirEntry.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntry.Extract.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntry.Read.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntry.Write.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntry.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntrySource.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipErrorAction.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.AddUpdate.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Check.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Events.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Extract.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Read.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Save.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.SaveSelfExtractor.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Selector.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.x-IEnumerable.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipInputStream.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipOutputStream.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zip/ZipSegmentedStream.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/Zlib.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/ZlibBaseStream.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/ZlibCodec.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/ZlibConstants.cs delete mode 100644 MinecraftClient/Protocol/Handlers/Compression/ZlibStream.cs diff --git a/MinecraftClient/AutoTimeout.cs b/MinecraftClient/AutoTimeout.cs index f92d35fe..786be4db 100644 --- a/MinecraftClient/AutoTimeout.cs +++ b/MinecraftClient/AutoTimeout.cs @@ -1,7 +1,5 @@ using System; -using System.Diagnostics; using System.Threading; -using System.Threading.Tasks; namespace MinecraftClient { @@ -30,14 +28,15 @@ namespace MinecraftClient /// Action to run /// Maximum timeout /// True if the action finished whithout timing out - public static bool Perform(Action action, TimeSpan timeout) { - Thread thread = new Thread(new ThreadStart(action)); + public static bool Perform(Action action, TimeSpan timeout) + { + Thread thread = new(new ThreadStart(action)); thread.Start(); + bool success = thread.Join(timeout); if (!success) thread.Interrupt(); - thread = null; return success; } } diff --git a/MinecraftClient/ChatBots/Alerts.cs b/MinecraftClient/ChatBots/Alerts.cs index 0f9a04d7..c5b1402a 100644 --- a/MinecraftClient/ChatBots/Alerts.cs +++ b/MinecraftClient/ChatBots/Alerts.cs @@ -1,9 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.IO; -using static System.Net.WebRequestMethods; namespace MinecraftClient.ChatBots { @@ -12,8 +8,8 @@ namespace MinecraftClient.ChatBots /// public class Alerts : ChatBot { - private string[] dictionary = new string[0]; - private string[] excludelist = new string[0]; + private string[] dictionary = Array.Empty(); + private string[] excludelist = Array.Empty(); private bool logToFile = false; /// diff --git a/MinecraftClient/ChatBots/AntiAFK.cs b/MinecraftClient/ChatBots/AntiAFK.cs index d078aae5..f4604484 100644 --- a/MinecraftClient/ChatBots/AntiAFK.cs +++ b/MinecraftClient/ChatBots/AntiAFK.cs @@ -10,14 +10,14 @@ namespace MinecraftClient.ChatBots public class AntiAFK : ChatBot { private int count; - private string pingparam; + private readonly string pingparam; private int timeping = 600; private int timepingMax = -1; private bool useTerrainHandling = false; private bool previousSneakState = false; private int walkRange = 5; - private int walkRetries = 10; - private Random random = new Random(); + private readonly int walkRetries = 10; + private readonly Random random = new(); /// /// This bot sends a /ping command every X seconds in order to stay non-afk. @@ -57,7 +57,7 @@ namespace MinecraftClient.ChatBots else { // Handle the random range - if (pingparam.Contains("-")) + if (pingparam.Contains('-')) { string[] parts = pingparam.Split("-"); @@ -85,10 +85,7 @@ namespace MinecraftClient.ChatBots if (timepingMax != -1 && timeping > timepingMax) { - int temporary = timepingMax; - timepingMax = timeping; - timeping = temporary; - + (timeping, timepingMax) = (timepingMax, timeping); LogToConsole(Translations.TryGet("bot.antiafk.swapping")); } diff --git a/MinecraftClient/ChatBots/AutoAttack.cs b/MinecraftClient/ChatBots/AutoAttack.cs index 55bc156d..f9c6e820 100644 --- a/MinecraftClient/ChatBots/AutoAttack.cs +++ b/MinecraftClient/ChatBots/AutoAttack.cs @@ -1,7 +1,7 @@ -using MinecraftClient.Mapping; -using System; +using System; using System.Collections.Generic; using System.IO; +using MinecraftClient.Mapping; namespace MinecraftClient.ChatBots { @@ -10,22 +10,22 @@ namespace MinecraftClient.ChatBots /// class AutoAttack : ChatBot { - private Dictionary entitiesToAttack = new Dictionary(); // mobs within attack range + private readonly Dictionary entitiesToAttack = new(); // mobs within attack range private int attackCooldown = 6; private int attackCooldownCounter = 6; private Double attackSpeed = 4; private Double attackCooldownSeconds; - private bool overrideAttackSpeed = false; - private int attackRange = 4; + private readonly bool overrideAttackSpeed = false; + private readonly int attackRange = 4; private Double serverTPS; private float health = 100; - private bool singleMode = true; - private bool priorityDistance = true; - private InteractType interactMode; - private bool attackHostile = true; - private bool attackPassive = false; - private string listMode = "blacklist"; - private List listedEntites = new(); + private readonly bool singleMode = true; + private readonly bool priorityDistance = true; + private readonly InteractType interactMode; + private readonly bool attackHostile = true; + private readonly bool attackPassive = false; + private readonly string listMode = "blacklist"; + private readonly List listedEntites = new(); public AutoAttack( string mode, string priority, bool overrideAttackSpeed = false, double cooldownSeconds = 1, InteractType interaction = InteractType.Attack) @@ -53,13 +53,13 @@ namespace MinecraftClient.ChatBots else { this.overrideAttackSpeed = overrideAttackSpeed; - this.attackCooldownSeconds = cooldownSeconds; + attackCooldownSeconds = cooldownSeconds; attackCooldown = Convert.ToInt32(Math.Truncate(attackCooldownSeconds / 0.1) + 1); } } - this.attackHostile = Settings.AutoAttack_Attack_Hostile; - this.attackPassive = Settings.AutoAttack_Attack_Passive; + attackHostile = Settings.AutoAttack_Attack_Hostile; + attackPassive = Settings.AutoAttack_Attack_Passive; if (Settings.AutoAttack_ListMode.Length > 0) { @@ -140,7 +140,7 @@ namespace MinecraftClient.ChatBots if (entitiesToAttack.ContainsKey(priorityEntity)) { // check entity distance and health again - if (shouldAttackEntity(entitiesToAttack[priorityEntity])) + if (ShouldAttackEntity(entitiesToAttack[priorityEntity])) { InteractEntity(priorityEntity, interactMode); // hit the entity! SendAnimation(Inventory.Hand.MainHand); // Arm animation @@ -152,7 +152,7 @@ namespace MinecraftClient.ChatBots foreach (KeyValuePair entity in entitiesToAttack) { // check that we are in range once again. - if (shouldAttackEntity(entity.Value)) + if (ShouldAttackEntity(entity.Value)) { InteractEntity(entity.Key, interactMode); // hit the entity! } @@ -169,7 +169,7 @@ namespace MinecraftClient.ChatBots public override void OnEntitySpawn(Entity entity) { - shouldAttackEntity(entity); + ShouldAttackEntity(entity); } public override void OnEntityDespawn(Entity entity) @@ -209,7 +209,7 @@ namespace MinecraftClient.ChatBots if (listedEntites.Count > 0) { bool inList = listedEntites.Contains(entity.Type); - result = listMode.Equals("blacklist") ? (inList ? false : result) : (inList ? true : false); + result = listMode.Equals("blacklist") ? (!inList && result) : (inList); } return result; @@ -217,7 +217,7 @@ namespace MinecraftClient.ChatBots public override void OnEntityMove(Entity entity) { - shouldAttackEntity(entity); + ShouldAttackEntity(entity); } public override void OnHealthUpdate(float health, int food) @@ -262,7 +262,7 @@ namespace MinecraftClient.ChatBots /// /// The entity to handle /// If the entity should be attacked - public bool shouldAttackEntity(Entity entity) + public bool ShouldAttackEntity(Entity entity) { if (!IsAllowedToAttack(entity) || entity.Health <= 0) return false; diff --git a/MinecraftClient/ChatBots/AutoCraft.cs b/MinecraftClient/ChatBots/AutoCraft.cs index 703a2fe9..a07bdf33 100644 --- a/MinecraftClient/ChatBots/AutoCraft.cs +++ b/MinecraftClient/ChatBots/AutoCraft.cs @@ -1,8 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.IO; +using System.Linq; using MinecraftClient.Inventory; using MinecraftClient.Mapping; @@ -16,23 +15,23 @@ namespace MinecraftClient.ChatBots private bool craftingFailed = false; private int inventoryInUse = -2; private int index = 0; - private Recipe recipeInUse; - private List actionSteps = new List(); + private Recipe? recipeInUse; + private readonly List actionSteps = new(); - private Location tableLocation = new Location(); + private Location tableLocation = new(); private bool abortOnFailure = true; private int updateDebounceValue = 2; private int updateDebounce = 0; - private int updateTimeoutValue = 10; + private readonly int updateTimeoutValue = 10; private int updateTimeout = 0; private string timeoutAction = "unspecified"; - private string configPath = @"autocraft\config.ini"; + private readonly string configPath = @"autocraft\config.ini"; private string lastRecipe = ""; // Used in parsing recipe config - private Dictionary recipes = new Dictionary(); + private readonly Dictionary recipes = new(); - private void resetVar() + private void ResetVar() { craftingFailed = false; waitingForTable = false; @@ -123,9 +122,10 @@ namespace MinecraftClient.ChatBots /// Materials needed and their position /// /// position start with 1, from left to right, top to bottom - public Dictionary Materials; + public Dictionary? Materials; public Recipe() { } + public Recipe(Dictionary materials, ItemType resultItem, ContainerType type) { Materials = materials; @@ -141,7 +141,7 @@ namespace MinecraftClient.ChatBots /// so that it can be used in crafting table public static Recipe ConvertToCraftingTable(Recipe recipe) { - if (recipe.CraftingAreaType == ContainerType.PlayerInventory) + if (recipe.CraftingAreaType == ContainerType.PlayerInventory && recipe.Materials != null) { if (recipe.Materials.ContainsKey(4)) { @@ -202,7 +202,7 @@ namespace MinecraftClient.ChatBots string name = args[1]; if (recipes.ContainsKey(name)) { - resetVar(); + ResetVar(); PrepareCrafting(recipes[name]); return ""; } @@ -221,32 +221,26 @@ namespace MinecraftClient.ChatBots else return GetHelp(); } - private string GetHelp() + private static string GetHelp() { return Translations.Get("bot.autoCraft.available_cmd", "load, list, reload, resetcfg, start, stop, help"); } private string GetCommandHelp(string cmd) { - switch (cmd.ToLower()) + return cmd.ToLower() switch { - case "load": - return Translations.Get("bot.autocraft.help.load"); - case "list": - return Translations.Get("bot.autocraft.help.list"); - case "reload": - return Translations.Get("bot.autocraft.help.reload"); - case "resetcfg": - return Translations.Get("bot.autocraft.help.resetcfg"); - case "start": - return Translations.Get("bot.autocraft.help.start"); - case "stop": - return Translations.Get("bot.autocraft.help.stop"); - case "help": - return Translations.Get("bot.autocraft.help.help"); - default: - return GetHelp(); - } +#pragma warning disable format // @formatter:off + "load" => Translations.Get("bot.autocraft.help.load"), + "list" => Translations.Get("bot.autocraft.help.list"), + "reload" => Translations.Get("bot.autocraft.help.reload"), + "resetcfg" => Translations.Get("bot.autocraft.help.resetcfg"), + "start" => Translations.Get("bot.autocraft.help.start"), + "stop" => Translations.Get("bot.autocraft.help.stop"), + "help" => Translations.Get("bot.autocraft.help.help"), + _ => GetHelp(), +#pragma warning restore format // @formatter:on + }; } #region Config handling @@ -312,7 +306,7 @@ namespace MinecraftClient.ChatBots // local variable for use in parsing config string section = ""; - Dictionary recipes = new Dictionary(); + Dictionary recipes = new(); foreach (string l in content) { @@ -323,20 +317,20 @@ namespace MinecraftClient.ChatBots if (line.Length <= 0) continue; - if (line[0] == '[' && line[line.Length - 1] == ']') + if (line[0] == '[' && line[^1] == ']') { - section = line.Substring(1, line.Length - 2).ToLower(); + section = line[1..^1].ToLower(); continue; } string key = line.Split('=')[0].ToLower(); if (!(line.Length > (key.Length + 1))) continue; - string value = line.Substring(key.Length + 1); + string value = line[(key.Length + 1)..]; switch (section) { - case "recipe": parseRecipe(key, value); break; - case "autocraft": parseMain(key, value); break; + case "recipe": ParseRecipe(key, value); break; + case "autocraft": ParseMain(key, value); break; } } @@ -358,12 +352,12 @@ namespace MinecraftClient.ChatBots } } - + } #region Method for parsing different section of config - private void parseMain(string key, string value) + private void ParseMain(string key, string value) { switch (key) { @@ -378,7 +372,7 @@ namespace MinecraftClient.ChatBots else throw new Exception(Translations.Get("bot.autoCraft.exception.invalid_table", key)); break; case "onfailure": - abortOnFailure = value.ToLower() == "abort" ? true : false; + abortOnFailure = value.ToLower() == "abort"; break; case "updatedebounce": updateDebounceValue = Convert.ToInt32(value); @@ -386,21 +380,21 @@ namespace MinecraftClient.ChatBots } } - private void parseRecipe(string key, string value) + private void ParseRecipe(string key, string value) { if (key.StartsWith("slot")) { - int slot = Convert.ToInt32(key[key.Length - 1].ToString()); + int slot = Convert.ToInt32(key[^1].ToString()); if (slot > 0 && slot < 10) { if (recipes.ContainsKey(lastRecipe)) { - ItemType itemType; - if (Enum.TryParse(value, true, out itemType)) + if (Enum.TryParse(value, true, out ItemType itemType)) { - if (recipes[lastRecipe].Materials != null && recipes[lastRecipe].Materials.Count > 0) + Dictionary? materials = recipes[lastRecipe].Materials; + if (materials != null && materials.Count > 0) { - recipes[lastRecipe].Materials.Add(slot, itemType); + materials.Add(slot, itemType); } else { @@ -450,8 +444,7 @@ namespace MinecraftClient.ChatBots case "result": if (recipes.ContainsKey(lastRecipe)) { - ItemType itemType; - if (Enum.TryParse(value, true, out itemType)) + if (Enum.TryParse(value, true, out ItemType itemType)) { recipes[lastRecipe].ResultItem = itemType; } @@ -487,7 +480,7 @@ namespace MinecraftClient.ChatBots // After table opened, we need to wait for server to update table inventory items waitingForUpdate = true; inventoryInUse = inventoryId; - PrepareCrafting(recipeInUse); + PrepareCrafting(recipeInUse!); } } } @@ -562,11 +555,14 @@ namespace MinecraftClient.ChatBots } } - foreach (KeyValuePair slot in recipe.Materials) + if (recipe.Materials != null) { - // Steps for moving items from inventory to crafting area - actionSteps.Add(new ActionStep(ActionType.LeftClick, inventoryInUse, slot.Value)); - actionSteps.Add(new ActionStep(ActionType.LeftClick, inventoryInUse, slot.Key)); + foreach (KeyValuePair slot in recipe.Materials) + { + // Steps for moving items from inventory to crafting area + actionSteps.Add(new ActionStep(ActionType.LeftClick, inventoryInUse, slot.Value)); + actionSteps.Add(new ActionStep(ActionType.LeftClick, inventoryInUse, slot.Key)); + } } if (actionSteps.Count > 0) { @@ -626,15 +622,15 @@ namespace MinecraftClient.ChatBots else { int[] slots = GetInventories()[step.InventoryID].SearchItem(step.ItemType); - if (slots.Count() > 0) + if (slots.Length > 0) { int ignoredSlot; - if (recipeInUse.CraftingAreaType == ContainerType.PlayerInventory) + if (recipeInUse!.CraftingAreaType == ContainerType.PlayerInventory) ignoredSlot = 9; else ignoredSlot = 10; slots = slots.Where(slot => slot >= ignoredSlot).ToArray(); - if (slots.Count() > 0) + if (slots.Length > 0) WindowAction(step.InventoryID, slots[0], WindowActionType.LeftClick); else craftingFailed = true; @@ -688,7 +684,6 @@ namespace MinecraftClient.ChatBots } HandleError(); } - } /// diff --git a/MinecraftClient/ChatBots/AutoDrop.cs b/MinecraftClient/ChatBots/AutoDrop.cs index cf3142f0..e101da54 100644 --- a/MinecraftClient/ChatBots/AutoDrop.cs +++ b/MinecraftClient/ChatBots/AutoDrop.cs @@ -1,8 +1,7 @@ -using MinecraftClient.Inventory; -using System; +using System; using System.Collections.Generic; using System.Linq; -using System.Text; +using MinecraftClient.Inventory; namespace MinecraftClient.ChatBots { @@ -18,10 +17,10 @@ namespace MinecraftClient.ChatBots private bool enable = true; private int updateDebounce = 0; - private int updateDebounceValue = 2; + private readonly int updateDebounceValue = 2; private int inventoryUpdated = -1; - private List itemList = new List(); + private readonly List itemList = new(); public AutoDrop(string mode, string itemList) { @@ -40,17 +39,11 @@ namespace MinecraftClient.ChatBots /// Item type array private ItemType[] ItemListParser(string itemList) { - string trimed = new string(itemList.Where(c => !char.IsWhiteSpace(c)).ToArray()); - string[] list = trimed.Split(','); - List result = new List(); - foreach (string t in list) - { - ItemType item; - if (Enum.TryParse(t, true, out item)) - { + string trimed = new(itemList.Where(c => !char.IsWhiteSpace(c)).ToArray()); + List result = new(); + foreach (string t in trimed.Split(',')) + if (Enum.TryParse(t, true, out ItemType item)) result.Add(item); - } - } return result.ToArray(); } @@ -71,8 +64,7 @@ namespace MinecraftClient.ChatBots case "add": if (args.Length >= 2) { - ItemType item; - if (Enum.TryParse(args[1], true, out item)) + if (Enum.TryParse(args[1], true, out ItemType item)) { itemList.Add(item); return Translations.Get("bot.autoDrop.added", item.ToString()); @@ -89,8 +81,7 @@ namespace MinecraftClient.ChatBots case "remove": if (args.Length >= 2) { - ItemType item; - if (Enum.TryParse(args[1], true, out item)) + if (Enum.TryParse(args[1], true, out ItemType item)) { if (itemList.Contains(item)) { @@ -109,7 +100,7 @@ namespace MinecraftClient.ChatBots } else { - return Translations.Get("cmd.inventory.help.usage") + ": remove "; + return Translations.Get("cmd.inventory.help.usage") + ": remove "; } case "list": if (itemList.Count > 0) @@ -155,7 +146,7 @@ namespace MinecraftClient.ChatBots } } - private string GetHelp() + private static string GetHelp() { return Translations.Get("general.available_cmd", "on, off, add, remove, list, mode"); } diff --git a/MinecraftClient/ChatBots/AutoEat.cs b/MinecraftClient/ChatBots/AutoEat.cs index 6e18d934..2866fe4a 100644 --- a/MinecraftClient/ChatBots/AutoEat.cs +++ b/MinecraftClient/ChatBots/AutoEat.cs @@ -1,8 +1,4 @@ using MinecraftClient.Inventory; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient.ChatBots { @@ -10,7 +6,7 @@ namespace MinecraftClient.ChatBots { byte LastSlot = 0; public static bool Eating = false; - private int HungerThreshold = 6; + private readonly int HungerThreshold = 6; private int DelayCounter = 0; public AutoEat(int Threshold) diff --git a/MinecraftClient/ChatBots/AutoFishing.cs b/MinecraftClient/ChatBots/AutoFishing.cs index 38001e6c..4e11eada 100644 --- a/MinecraftClient/ChatBots/AutoFishing.cs +++ b/MinecraftClient/ChatBots/AutoFishing.cs @@ -1,9 +1,6 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using MinecraftClient.Mapping; using MinecraftClient.Inventory; +using MinecraftClient.Mapping; namespace MinecraftClient.ChatBots { diff --git a/MinecraftClient/ChatBots/AutoRelog.cs b/MinecraftClient/ChatBots/AutoRelog.cs index a56bc030..b6f5a6e6 100644 --- a/MinecraftClient/ChatBots/AutoRelog.cs +++ b/MinecraftClient/ChatBots/AutoRelog.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Text; namespace MinecraftClient.ChatBots @@ -10,11 +8,11 @@ namespace MinecraftClient.ChatBots /// public class AutoRelog : ChatBot { - private static Random random = new Random(); - private string[] dictionary = new string[0]; - private int attempts; - private int delayMin; - private int delayMax; + private static readonly Random random = new(); + private string[] dictionary = Array.Empty(); + private readonly int attempts; + private readonly int delayMin; + private readonly int delayMax; /// /// This bot automatically re-join the server if kick message contains predefined string @@ -100,7 +98,7 @@ namespace MinecraftClient.ChatBots return false; } - private void LaunchDelayedReconnection(string msg) + private void LaunchDelayedReconnection(string? msg) { int delay = random.Next(delayMin, delayMax); LogDebugToConsoleTranslated(String.IsNullOrEmpty(msg) ? "bot.autoRelog.reconnect_always" : "bot.autoRelog.reconnect", msg); @@ -113,7 +111,7 @@ namespace MinecraftClient.ChatBots { if (Settings.AutoRelog_Enabled) { - AutoRelog bot = new AutoRelog(Settings.AutoRelog_Delay_Min, Settings.AutoRelog_Delay_Max, Settings.AutoRelog_Retries); + AutoRelog bot = new(Settings.AutoRelog_Delay_Min, Settings.AutoRelog_Delay_Max, Settings.AutoRelog_Retries); bot.Initialize(); return bot.OnDisconnect(reason, message); } diff --git a/MinecraftClient/ChatBots/AutoRespond.cs b/MinecraftClient/ChatBots/AutoRespond.cs index 7d17625f..2b0738b5 100644 --- a/MinecraftClient/ChatBots/AutoRespond.cs +++ b/MinecraftClient/ChatBots/AutoRespond.cs @@ -1,6 +1,6 @@ using System; -using System.IO; using System.Collections.Generic; +using System.IO; using System.Text; using System.Text.RegularExpressions; @@ -11,9 +11,9 @@ namespace MinecraftClient.ChatBots /// class AutoRespond : ChatBot { - private string matchesFile; - private bool matchColors; - private List respondRules; + private readonly string matchesFile; + private readonly bool matchColors; + private List? respondRules; private enum MessageType { Public, Private, Other }; /// @@ -31,13 +31,13 @@ namespace MinecraftClient.ChatBots /// private class RespondRule { - private Regex regex; - private string match; - private string actionPublic; - private string actionPrivate; - private string actionOther; - private bool ownersOnly; - private TimeSpan cooldown; + private readonly Regex? regex; + private readonly string? match; + private readonly string? actionPublic; + private readonly string? actionPrivate; + private readonly string? actionOther; + private readonly bool ownersOnly; + private readonly TimeSpan cooldown; private DateTime cooldownExpiration; /// @@ -49,16 +49,16 @@ namespace MinecraftClient.ChatBots /// Internal command to run for any other messages /// Only match messages from bot owners /// Minimal cooldown between two matches - public RespondRule(Regex regex, string actionPublic, string actionPrivate, string actionOther, bool ownersOnly, TimeSpan cooldown) + public RespondRule(Regex regex, string? actionPublic, string? actionPrivate, string? actionOther, bool ownersOnly, TimeSpan cooldown) { this.regex = regex; - this.match = null; + match = null; this.actionPublic = actionPublic; this.actionPrivate = actionPrivate; this.actionOther = actionOther; this.ownersOnly = ownersOnly; this.cooldown = cooldown; - this.cooldownExpiration = DateTime.MinValue; + cooldownExpiration = DateTime.MinValue; } /// @@ -69,16 +69,16 @@ namespace MinecraftClient.ChatBots /// Internal command to run for private messages /// Only match messages from bot owners /// Minimal cooldown between two matches - public RespondRule(string match, string actionPublic, string actionPrivate, string actionOther, bool ownersOnly, TimeSpan cooldown) + public RespondRule(string? match, string? actionPublic, string? actionPrivate, string? actionOther, bool ownersOnly, TimeSpan cooldown) { - this.regex = null; + regex = null; this.match = match; this.actionPublic = actionPublic; this.actionPrivate = actionPrivate; this.actionOther = actionOther; this.ownersOnly = ownersOnly; this.cooldown = cooldown; - this.cooldownExpiration = DateTime.MinValue; + cooldownExpiration = DateTime.MinValue; } /// @@ -89,12 +89,12 @@ namespace MinecraftClient.ChatBots /// Type of the message public/private message, or other message /// Dictionary to populate with match variables in case of Regex match /// Internal command to run as a response to this user, or null if no match has been detected - public string Match(string username, string message, MessageType msgType, Dictionary localVars) + public string? Match(string username, string message, MessageType msgType, Dictionary localVars) { if (DateTime.Now < cooldownExpiration) return null; - string toSend = null; + string? toSend = null; if (ownersOnly && (String.IsNullOrEmpty(username) || !Settings.Bots_Owners.Contains(username.ToLower()))) return null; @@ -166,11 +166,11 @@ namespace MinecraftClient.ChatBots { if (File.Exists(matchesFile)) { - Regex matchRegex = null; - string matchString = null; - string matchAction = null; - string matchActionPrivate = null; - string matchActionOther = null; + Regex? matchRegex = null; + string? matchString = null; + string? matchAction = null; + string? matchActionPrivate = null; + string? matchActionOther = null; bool ownersOnly = false; TimeSpan cooldown = TimeSpan.Zero; respondRules = new List(); @@ -182,9 +182,9 @@ namespace MinecraftClient.ChatBots string line = lineRAW.Split('#')[0].Trim(); if (line.Length > 0) { - if (line[0] == '[' && line[line.Length - 1] == ']') + if (line[0] == '[' && line[^1] == ']') { - switch (line.Substring(1, line.Length - 2).ToLower()) + switch (line[1..^1].ToLower()) { case "match": CheckAddMatch(matchRegex, matchString, matchAction, matchActionPrivate, matchActionOther, ownersOnly, cooldown); @@ -203,7 +203,7 @@ namespace MinecraftClient.ChatBots string argName = line.Split('=')[0]; if (line.Length > (argName.Length + 1)) { - string argValue = line.Substring(argName.Length + 1); + string argValue = line[(argName.Length + 1)..]; switch (argName.ToLower()) { case "regex": matchRegex = new Regex(argValue); break; @@ -236,7 +236,7 @@ namespace MinecraftClient.ChatBots /// Action if the matching message is private /// Only match messages from bot owners /// Minimal cooldown between two matches - private void CheckAddMatch(Regex matchRegex, string matchString, string matchAction, string matchActionPrivate, string matchActionOther, bool ownersOnly, TimeSpan cooldown) + private void CheckAddMatch(Regex? matchRegex, string? matchString, string? matchAction, string? matchActionPrivate, string? matchActionOther, bool ownersOnly, TimeSpan cooldown) { if (matchRegex != null || matchString != null || matchAction != null || matchActionPrivate != null || matchActionOther != null || ownersOnly || cooldown != TimeSpan.Zero) { @@ -248,7 +248,7 @@ namespace MinecraftClient.ChatBots { if (matchRegex != null || matchString != null) { - respondRules.Add(rule); + respondRules!.Add(rule); LogDebugToConsoleTranslated("bot.autoRespond.loaded_match", rule); } else LogDebugToConsoleTranslated("bot.autoRespond.no_trigger", rule); @@ -264,7 +264,7 @@ namespace MinecraftClient.ChatBots public override void GetText(string text) { //Remove colour codes - if (!this.matchColors) + if (!matchColors) text = GetVerbatim(text); //Get Message type @@ -279,13 +279,13 @@ namespace MinecraftClient.ChatBots //Do not process messages sent by the bot itself if (msgType == MessageType.Other || sender != Settings.Username) { - foreach (RespondRule rule in respondRules) + foreach (RespondRule rule in respondRules!) { - Dictionary localVars = new Dictionary(); - string toPerform = rule.Match(sender, message, msgType, localVars); + Dictionary localVars = new(); + string? toPerform = rule.Match(sender, message, msgType, localVars); if (!String.IsNullOrEmpty(toPerform)) { - string response = null; + string? response = null; LogToConsoleTranslated("bot.autoRespond.match_run", toPerform); PerformInternalCommand(toPerform, ref response, localVars); if (!String.IsNullOrEmpty(response)) diff --git a/MinecraftClient/ChatBots/BotsCommand.cs b/MinecraftClient/ChatBots/BotsCommand.cs index 309e3e0c..72913de3 100644 --- a/MinecraftClient/ChatBots/BotsCommand.cs +++ b/MinecraftClient/ChatBots/BotsCommand.cs @@ -1,7 +1,5 @@ -using MinecraftClient.Mapping; using System; using System.Collections.Generic; -using System.Linq; using System.Text; namespace MinecraftClient.Commands @@ -12,11 +10,11 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "bots [list|unload ]"; } } public override string CmdDesc { get { return "cmd.bots.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { - if (hasArg(command)) + if (HasArg(command)) { - string[] args = getArgs(command); + string[] args = GetArgs(command); if (args.Length == 1) { diff --git a/MinecraftClient/ChatBots/ChatLog.cs b/MinecraftClient/ChatBots/ChatLog.cs index 1eaffb08..cc2e81b5 100644 --- a/MinecraftClient/ChatBots/ChatLog.cs +++ b/MinecraftClient/ChatBots/ChatLog.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.IO; namespace MinecraftClient.ChatBots @@ -13,13 +10,13 @@ namespace MinecraftClient.ChatBots public class ChatLog : ChatBot { public enum MessageFilter { AllText, AllMessages, OnlyChat, OnlyWhispers, OnlyInternalCommands }; - private bool dateandtime; - private bool saveOther = true; - private bool saveChat = true; - private bool savePrivate = true; - private bool saveInternal = true; - private string logfile; - private object logfileLock = new object(); + private readonly bool dateandtime; + private readonly bool saveOther = true; + private readonly bool saveChat = true; + private readonly bool savePrivate = true; + private readonly bool saveInternal = true; + private readonly string logfile; + private readonly object logfileLock = new(); /// /// This bot saves the messages received in the specified file, with some filters and date/time tagging. @@ -70,15 +67,17 @@ namespace MinecraftClient.ChatBots public static MessageFilter str2filter(string filtername) { - switch (Settings.ToLowerIfNeed(filtername)) + return Settings.ToLowerIfNeed(filtername) switch { - case "all": return MessageFilter.AllText; - case "messages": return MessageFilter.AllMessages; - case "chat": return MessageFilter.OnlyChat; - case "private": return MessageFilter.OnlyWhispers; - case "internal": return MessageFilter.OnlyInternalCommands; - default: return MessageFilter.AllText; - } +#pragma warning disable format // @formatter:off + "all" => MessageFilter.AllText, + "messages" => MessageFilter.AllMessages, + "chat" => MessageFilter.OnlyChat, + "private" => MessageFilter.OnlyWhispers, + "internal" => MessageFilter.OnlyInternalCommands, + _ => MessageFilter.AllText, +#pragma warning restore format // @formatter:on + }; } public override void GetText(string text) @@ -89,37 +88,37 @@ namespace MinecraftClient.ChatBots if (saveChat && IsChatMessage(text, ref message, ref sender)) { - save("Chat " + sender + ": " + message); + Save("Chat " + sender + ": " + message); } else if (savePrivate && IsPrivateMessage(text, ref message, ref sender)) { - save("Private " + sender + ": " + message); + Save("Private " + sender + ": " + message); } else if (saveOther) { - save("Other: " + text); + Save("Other: " + text); } } - public override void OnInternalCommand(string commandName,string commandParams, string result) + public override void OnInternalCommand(string commandName, string commandParams, string result) { if (saveInternal) { - save(string.Format("Internal {0}({1}): {2}", commandName, commandParams, result)); + Save(string.Format("Internal {0}({1}): {2}", commandName, commandParams, result)); } } - private void save(string tosave) + private void Save(string tosave) { if (dateandtime) tosave = GetTimestamp() + ' ' + tosave; lock (logfileLock) { - string directory = Path.GetDirectoryName(logfile); + string? directory = Path.GetDirectoryName(logfile); if (!String.IsNullOrEmpty(directory) && !Directory.Exists(directory)) Directory.CreateDirectory(directory); - FileStream stream = new FileStream(logfile, FileMode.OpenOrCreate); - StreamWriter writer = new StreamWriter(stream); + FileStream stream = new(logfile, FileMode.OpenOrCreate); + StreamWriter writer = new(stream); stream.Seek(0, SeekOrigin.End); writer.WriteLine(tosave); writer.Dispose(); diff --git a/MinecraftClient/ChatBots/FollowPlayer.cs b/MinecraftClient/ChatBots/FollowPlayer.cs index 92af0b9c..e03eb253 100644 --- a/MinecraftClient/ChatBots/FollowPlayer.cs +++ b/MinecraftClient/ChatBots/FollowPlayer.cs @@ -8,8 +8,8 @@ namespace MinecraftClient.ChatBots { private string? _playerToFollow = null; private int _updateCounter = 0; - private int _updateLimit; - private int _stopAtDistance; + private readonly int _updateLimit; + private readonly int _stopAtDistance; private bool _unsafeEnabled = false; public FollowPlayer(int updateLimit = 15, int stopAtDistance = 3) @@ -112,7 +112,7 @@ namespace MinecraftClient.ChatBots return; // Stop at specified distance from plater (prevents pushing player around) - double distance = Distance(entity.Location, GetCurrentLocation()); + double distance = entity.Location.Distance(GetCurrentLocation()); if (distance < _stopAtDistance) return; @@ -154,14 +154,6 @@ namespace MinecraftClient.ChatBots } } - private double Distance(Location location1, Location location2) - { - return Math.Sqrt( - ((location1.X - location2.X) * (location1.X - location2.X)) + - ((location1.Y - location2.Y) * (location1.Y - location2.Y)) + - ((location1.Z - location2.Z) * (location1.Z - location2.Z))); - } - private bool CanMoveThere(Location location) { ChunkColumn? chunkColumn = GetWorld().GetChunkColumn(location); diff --git a/MinecraftClient/ChatBots/HangmanGame.cs b/MinecraftClient/ChatBots/HangmanGame.cs index 49ec5ea1..c41324af 100644 --- a/MinecraftClient/ChatBots/HangmanGame.cs +++ b/MinecraftClient/ChatBots/HangmanGame.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Text; namespace MinecraftClient.ChatBots @@ -12,14 +10,14 @@ namespace MinecraftClient.ChatBots public class HangmanGame : ChatBot { private int vie = 0; - private int vie_param = 10; + private readonly int vie_param = 10; private int compteur = 0; - private int compteur_param = 3000; //5 minutes + private readonly int compteur_param = 3000; //5 minutes private bool running = false; private bool[] discovered; private string word = ""; private string letters = ""; - private bool English; + private readonly bool English; /// /// Le jeu du Pendu / Hangman Game @@ -29,6 +27,7 @@ namespace MinecraftClient.ChatBots public HangmanGame(bool english) { English = english; + discovered = Array.Empty(); } public override void Update() @@ -61,7 +60,7 @@ namespace MinecraftClient.ChatBots switch (message) { case "start": - start(); + Start(); break; case "stop": running = false; @@ -108,11 +107,11 @@ namespace MinecraftClient.ChatBots if (running) { - SendText(English ? ("Mysterious word: " + word_cached + " (lives : " + vie + ")") - : ("Mot mystère : " + word_cached + " (vie : " + vie + ")")); + SendText(English ? ("Mysterious word: " + WordCached + " (lives : " + vie + ")") + : ("Mot mystère : " + WordCached + " (vie : " + vie + ")")); } - if (winner) + if (Winner) { SendText(English ? ("Congrats, " + username + '!') : ("Félicitations, " + username + " !")); running = false; @@ -124,22 +123,22 @@ namespace MinecraftClient.ChatBots } } - private void start() + private void Start() { vie = vie_param; running = true; letters = ""; - word = chooseword(); + word = Chooseword(); compteur = compteur_param; discovered = new bool[word.Length]; SendText(English ? "Hangman v1.0 - By ORelio" : "Pendu v1.0 - Par ORelio"); - SendText(English ? ("Mysterious word: " + word_cached + " (lives : " + vie + ")") - : ("Mot mystère : " + word_cached + " (vie : " + vie + ")")); + SendText(English ? ("Mysterious word: " + WordCached + " (lives : " + vie + ")") + : ("Mot mystère : " + WordCached + " (vie : " + vie + ")")); SendText(English ? ("Try some letters ... :)") : ("Proposez une lettre ... :)")); } - private string chooseword() + private string Chooseword() { if (System.IO.File.Exists(English ? Settings.Hangman_FileWords_EN : Settings.Hangman_FileWords_FR)) { @@ -153,7 +152,7 @@ namespace MinecraftClient.ChatBots } } - private string word_cached + private string WordCached { get { @@ -170,7 +169,7 @@ namespace MinecraftClient.ChatBots } } - private bool winner + private bool Winner { get { diff --git a/MinecraftClient/ChatBots/Mailer.cs b/MinecraftClient/ChatBots/Mailer.cs index f22b82ba..8752d1fd 100644 --- a/MinecraftClient/ChatBots/Mailer.cs +++ b/MinecraftClient/ChatBots/Mailer.cs @@ -1,8 +1,8 @@ using System; +using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; -using System.Collections.Generic; namespace MinecraftClient.ChatBots { @@ -23,7 +23,7 @@ namespace MinecraftClient.ChatBots /// Ignore list public static IgnoreList FromFile(string filePath) { - IgnoreList ignoreList = new IgnoreList(); + IgnoreList ignoreList = new(); foreach (string line in FileMonitor.ReadAllLinesWithRetries(filePath)) { if (!line.StartsWith("#")) @@ -42,7 +42,7 @@ namespace MinecraftClient.ChatBots /// Path to destination file public void SaveToFile(string filePath) { - List lines = new List(); + List lines = new(); lines.Add("#Ignored Players"); foreach (string player in this) lines.Add(player); @@ -62,7 +62,7 @@ namespace MinecraftClient.ChatBots /// Mail database public static MailDatabase FromFile(string filePath) { - MailDatabase database = new MailDatabase(); + MailDatabase database = new(); Dictionary> iniFileDict = INIFile.ParseFile(FileMonitor.ReadAllLinesWithRetries(filePath)); foreach (KeyValuePair> iniSection in iniFileDict) { @@ -83,17 +83,21 @@ namespace MinecraftClient.ChatBots /// Path to destination file public void SaveToFile(string filePath) { - Dictionary> iniFileDict = new Dictionary>(); + Dictionary> iniFileDict = new(); int mailCount = 0; foreach (Mail mail in this) { mailCount++; - Dictionary iniSection = new Dictionary(); - iniSection["sender"] = mail.Sender; - iniSection["recipient"] = mail.Recipient; - iniSection["content"] = mail.Content; - iniSection["timestamp"] = mail.DateSent.ToString(); - iniSection["anonymous"] = mail.Anonymous.ToString(); + Dictionary iniSection = new() + { +#pragma warning disable format // @formatter:off + ["sender"] = mail.Sender, + ["recipient"] = mail.Recipient, + ["content"] = mail.Content, + ["timestamp"] = mail.DateSent.ToString(), + ["anonymous"] = mail.Anonymous.ToString() +#pragma warning restore format // @formatter:on + }; iniFileDict["mail" + mailCount] = iniSection; } FileMonitor.WriteAllLinesWithRetries(filePath, INIFile.Generate(iniFileDict, "Mail Database")); @@ -105,24 +109,24 @@ namespace MinecraftClient.ChatBots /// private class Mail { - private string sender; - private string senderLower; - private string recipient; - private string recipientLower; - private string message; - private DateTime datesent; + private readonly string sender; + private readonly string senderLower; + private readonly string recipient; + private readonly string recipientLower; + private readonly string message; + private readonly DateTime datesent; private bool delivered; - private bool anonymous; + private readonly bool anonymous; public Mail(string sender, string recipient, string message, bool anonymous, DateTime datesent) { this.sender = sender; - this.senderLower = sender.ToLower(); + senderLower = sender.ToLower(); this.recipient = recipient; - this.recipientLower = recipient.ToLower(); + recipientLower = recipient.ToLower(); this.message = message; this.datesent = datesent; - this.delivered = false; + delivered = false; this.anonymous = anonymous; } @@ -132,9 +136,9 @@ namespace MinecraftClient.ChatBots public string RecipientLowercase { get { return recipientLower; } } public string Content { get { return message; } } public DateTime DateSent { get { return datesent; } } - public bool Delivered { get { return delivered; } } + public bool Delivered => delivered; public bool Anonymous { get { return anonymous; } } - public void setDelivered() { delivered = true; } + public void SetDelivered() { delivered = true; } public override string ToString() { @@ -145,11 +149,11 @@ namespace MinecraftClient.ChatBots // Internal variables private int maxMessageLength = 0; private DateTime nextMailSend = DateTime.Now; - private MailDatabase mailDatabase = new MailDatabase(); - private IgnoreList ignoreList = new IgnoreList(); - private FileMonitor mailDbFileMonitor; - private FileMonitor ignoreListFileMonitor; - private object readWriteLock = new object(); + private MailDatabase mailDatabase = new(); + private IgnoreList ignoreList = new(); + private FileMonitor? mailDbFileMonitor; + private FileMonitor? ignoreListFileMonitor; + private readonly object readWriteLock = new(); /// /// Initialization of the Mailer bot @@ -207,8 +211,8 @@ namespace MinecraftClient.ChatBots } //Initialize file monitors. In case the bot needs to unload for some reason in the future, do not forget to .Dispose() them - mailDbFileMonitor = new FileMonitor(Path.GetDirectoryName(Settings.Mailer_DatabaseFile), Path.GetFileName(Settings.Mailer_DatabaseFile), FileMonitorCallback); - ignoreListFileMonitor = new FileMonitor(Path.GetDirectoryName(Settings.Mailer_IgnoreListFile), Path.GetFileName(Settings.Mailer_IgnoreListFile), FileMonitorCallback); + mailDbFileMonitor = new FileMonitor(Path.GetDirectoryName(Settings.Mailer_DatabaseFile)!, Path.GetFileName(Settings.Mailer_DatabaseFile), FileMonitorCallback); + ignoreListFileMonitor = new FileMonitor(Path.GetDirectoryName(Settings.Mailer_IgnoreListFile)!, Path.GetFileName(Settings.Mailer_IgnoreListFile), FileMonitorCallback); RegisterChatBotCommand("mailer", Translations.Get("bot.mailer.cmd"), "mailer ", ProcessInternalCommand); } @@ -246,7 +250,7 @@ namespace MinecraftClient.ChatBots && mailDatabase.Count < Settings.Mailer_MaxDatabaseSize && mailDatabase.Where(mail => mail.SenderLowercase == usernameLower).Count() < Settings.Mailer_MaxMailsPerPlayer) { - Queue args = new Queue(Command.getArgs(message)); + Queue args = new(Command.GetArgs(message)); if (args.Count >= 2) { bool anonymous = (command == "tellonym"); @@ -257,7 +261,7 @@ namespace MinecraftClient.ChatBots { if (message.Length <= maxMessageLength) { - Mail mail = new Mail(username, recipient, message, anonymous, DateTime.Now); + Mail mail = new(username, recipient, message, anonymous, DateTime.Now); LogToConsoleTranslated("bot.mailer.saving", mail.ToString()); lock (readWriteLock) { @@ -291,12 +295,12 @@ namespace MinecraftClient.ChatBots LogDebugToConsoleTranslated("bot.mailer.process_mails", DateTime.Now); // Process at most 3 mails at a time to avoid spamming. Other mails will be processed on next mail send - HashSet onlinePlayersLowercase = new HashSet(GetOnlinePlayers().Select(name => name.ToLower())); + HashSet onlinePlayersLowercase = new(GetOnlinePlayers().Select(name => name.ToLower())); foreach (Mail mail in mailDatabase.Where(mail => !mail.Delivered && onlinePlayersLowercase.Contains(mail.RecipientLowercase)).Take(3)) { string sender = mail.Anonymous ? "Anonymous" : mail.Sender; SendPrivateMessage(mail.Recipient, sender + " mailed: " + mail.Content); - mail.setDelivered(); + mail.SetDelivered(); LogDebugToConsoleTranslated("bot.mailer.delivered", mail.ToString()); } @@ -336,7 +340,7 @@ namespace MinecraftClient.ChatBots switch (commandName) { case "getmails": // Sorry, I (ReinforceZwei) replaced "=" to "-" because it would affect the parsing of translation file (key=value) - return Translations.Get("bot.mailer.cmd.getmails", string.Join("\n", mailDatabase)); + return Translations.Get("bot.mailer.cmd.getmails", string.Join("\n", mailDatabase)); case "getignored": return Translations.Get("bot.mailer.cmd.getignored", string.Join("\n", ignoreList)); diff --git a/MinecraftClient/ChatBots/Map.cs b/MinecraftClient/ChatBots/Map.cs index a6793e1f..d84a1117 100644 --- a/MinecraftClient/ChatBots/Map.cs +++ b/MinecraftClient/ChatBots/Map.cs @@ -1,17 +1,17 @@ using System; using System.Collections.Generic; +using System.Drawing; using System.IO; using MinecraftClient.Mapping; -using System.Drawing; using MinecraftClient.Protocol.Handlers; namespace MinecraftClient.ChatBots { class Map : ChatBot { - private string baseDirectory = @"Rendered_Maps"; + private readonly string baseDirectory = @"Rendered_Maps"; - private Dictionary cachedMaps = new(); + private readonly Dictionary cachedMaps = new(); private bool shouldResize = true; private int resizeTo = 256; private bool autoRenderOnUpdate = true; @@ -40,7 +40,7 @@ namespace MinecraftClient.ChatBots { if (deleteAllOnExit) { - DirectoryInfo di = new DirectoryInfo(baseDirectory); + DirectoryInfo di = new(baseDirectory); FileInfo[] files = di.GetFiles(); foreach (FileInfo file in files) @@ -101,19 +101,20 @@ namespace MinecraftClient.ChatBots if (columnsUpdated == 0 && cachedMaps.ContainsKey(mapid)) return; - McMap map = new McMap(); - - map.MapId = mapid; - map.Scale = scale; - map.TrackingPosition = trackingPosition; - map.Locked = locked; - map.MapIcons = icons; - map.Width = rowsUpdated; - map.Height = columnsUpdated; - map.X = mapCoulmnX; - map.Z = mapRowZ; - map.Colors = colors; - map.LastUpdated = DateTime.Now; + McMap map = new() + { + MapId = mapid, + Scale = scale, + TrackingPosition = trackingPosition, + Locked = locked, + MapIcons = icons, + Width = rowsUpdated, + Height = columnsUpdated, + X = mapCoulmnX, + Z = mapRowZ, + Colors = colors, + LastUpdated = DateTime.Now + }; if (!cachedMaps.ContainsKey(mapid)) { @@ -139,7 +140,7 @@ namespace MinecraftClient.ChatBots if (File.Exists(fileName)) File.Delete(fileName); - Bitmap image = new Bitmap(map.Width, map.Height); + Bitmap image = new(map.Width, map.Height); for (int x = 0; x < map.Width; ++x) { @@ -168,7 +169,7 @@ namespace MinecraftClient.ChatBots } private Bitmap ResizeBitmap(Bitmap sourceBMP, int width, int height) { - Bitmap result = new Bitmap(width, height); + Bitmap result = new(width, height); using (Graphics g = Graphics.FromImage(result)) g.DrawImage(sourceBMP, 0, 0, width, height); return result; diff --git a/MinecraftClient/ChatBots/PlayerListLogger.cs b/MinecraftClient/ChatBots/PlayerListLogger.cs index 0cf97194..b15d5f92 100644 --- a/MinecraftClient/ChatBots/PlayerListLogger.cs +++ b/MinecraftClient/ChatBots/PlayerListLogger.cs @@ -1,8 +1,6 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Text; -using static System.Net.Mime.MediaTypeNames; namespace MinecraftClient.ChatBots { @@ -13,8 +11,8 @@ namespace MinecraftClient.ChatBots public class PlayerListLogger : ChatBot { private int count; - private int timeping; - private string file; + private readonly int timeping; + private readonly string file; /// /// This bot sends a /list command every X seconds and save the result. @@ -35,24 +33,14 @@ namespace MinecraftClient.ChatBots count++; if (count == timeping) { - string[] playerList = GetOnlinePlayers(); - - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < playerList.Length; i++) - { - sb.Append(playerList[i]); - - // Do not add a comma after the last username - if (i != playerList.Length - 1) - sb.Append(", "); - } + DateTime now = DateTime.Now; LogDebugToConsole("Saving Player List"); - DateTime now = DateTime.Now; - string TimeStamp = "[" + now.Year + '/' + now.Month + '/' + now.Day + ' ' + now.Hour + ':' + now.Minute + ']'; - System.IO.File.AppendAllText(file, TimeStamp + "\n" + sb.ToString() + "\n\n"); + StringBuilder sb = new(); + sb.AppendLine(string.Format("[{0}/{1}/{2} {3}:{4}]", now.Year, now.Month, now.Day, now.Hour, now.Minute)); + sb.AppendLine(string.Join(", ", GetOnlinePlayers())).AppendLine(); + System.IO.File.AppendAllText(file, sb.ToString()); count = 0; } diff --git a/MinecraftClient/ChatBots/Reload.cs b/MinecraftClient/ChatBots/Reload.cs index 83a92a29..f4063db7 100644 --- a/MinecraftClient/ChatBots/Reload.cs +++ b/MinecraftClient/ChatBots/Reload.cs @@ -1,8 +1,4 @@ -using MinecraftClient.Mapping; -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient.Commands { @@ -12,7 +8,7 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "reload"; } } public override string CmdDesc { get { return "cmd.reload.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { handler.Log.Info(Translations.TryGet("cmd.reload.started")); handler.ReloadSettings(); diff --git a/MinecraftClient/ChatBots/RemoteControl.cs b/MinecraftClient/ChatBots/RemoteControl.cs index 988640f4..3baae1a1 100644 --- a/MinecraftClient/ChatBots/RemoteControl.cs +++ b/MinecraftClient/ChatBots/RemoteControl.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient.ChatBots { @@ -17,7 +14,7 @@ namespace MinecraftClient.ChatBots string command = "", sender = ""; if (IsPrivateMessage(text, ref command, ref sender) && Settings.Bots_Owners.Contains(sender.ToLower().Trim())) { - string response = ""; + string? response = ""; PerformInternalCommand(command, ref response); response = GetVerbatim(response); foreach (char disallowedChar in McClient.GetDisallowedChatCharacters()) diff --git a/MinecraftClient/ChatBots/ReplayCapture.cs b/MinecraftClient/ChatBots/ReplayCapture.cs index 0685ba25..25ea1557 100644 --- a/MinecraftClient/ChatBots/ReplayCapture.cs +++ b/MinecraftClient/ChatBots/ReplayCapture.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using MinecraftClient.Protocol; namespace MinecraftClient.ChatBots @@ -11,15 +9,16 @@ namespace MinecraftClient.ChatBots /// public class ReplayCapture : ChatBot { - private ReplayHandler replay; - private int backupInterval = 3000; // Unit: second * 10 + private ReplayHandler? replay; + private readonly int backupInterval = 3000; // Unit: second * 10 private int backupCounter = -1; public ReplayCapture(int backupInterval) { if (backupInterval != -1) this.backupInterval = backupInterval * 10; - else this.backupInterval = -1; + else + this.backupInterval = -1; } public override void Initialize() @@ -34,12 +33,12 @@ namespace MinecraftClient.ChatBots public override void OnNetworkPacket(int packetID, List packetData, bool isLogin, bool isInbound) { - replay.AddPacket(packetID, packetData, isLogin, isInbound); + replay!.AddPacket(packetID, packetData, isLogin, isInbound); } public override void Update() { - if (backupInterval > 0 && replay.RecordRunning) + if (backupInterval > 0 && replay!.RecordRunning) { if (backupCounter <= 0) { @@ -52,7 +51,7 @@ namespace MinecraftClient.ChatBots public override bool OnDisconnect(DisconnectReason reason, string message) { - replay.OnShutDown(); + replay!.OnShutDown(); return base.OnDisconnect(reason, message); } @@ -60,7 +59,7 @@ namespace MinecraftClient.ChatBots { try { - if (replay.RecordRunning) + if (replay!.RecordRunning) { if (args.Length > 0) { diff --git a/MinecraftClient/ChatBots/Script.cs b/MinecraftClient/ChatBots/Script.cs index 204d32be..84ee6483 100644 --- a/MinecraftClient/ChatBots/Script.cs +++ b/MinecraftClient/ChatBots/Script.cs @@ -1,13 +1,10 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using Microsoft.CSharp; -using System.CodeDom.Compiler; -using System.Reflection; using System.Diagnostics; using System.IO; +using System.Reflection; +using System.Text; +using System.Threading; namespace MinecraftClient.ChatBots { @@ -17,32 +14,32 @@ namespace MinecraftClient.ChatBots public class Script : ChatBot { - private string file; - private string[] lines = new string[0]; - private string[] args = new string[0]; + private string? file; + private string[] lines = Array.Empty(); + private string[] args = Array.Empty(); private int sleepticks = 10; private int nextline = 0; - private string owner; + private readonly string? owner; private bool csharp; - private Thread thread; - private Dictionary localVars; + private Thread? thread; + private readonly Dictionary? localVars; public Script(string filename) { ParseArguments(filename); } - public Script(string filename, string ownername, Dictionary localVars) + public Script(string filename, string? ownername, Dictionary? localVars) : this(filename) { - this.owner = ownername; + owner = ownername; this.localVars = localVars; } private void ParseArguments(string argstr) { - List args = new List(); - StringBuilder str = new StringBuilder(); + List args = new(); + StringBuilder str = new(); bool escape = false; bool quotes = false; @@ -115,9 +112,9 @@ namespace MinecraftClient.ChatBots string caller = "Script"; try { - StackFrame frame = new StackFrame(1); - MethodBase method = frame.GetMethod(); - Type type = method.DeclaringType; + StackFrame frame = new(1); + MethodBase method = frame.GetMethod()!; + Type type = method.DeclaringType!; caller = type.Name; } catch { } @@ -130,7 +127,7 @@ namespace MinecraftClient.ChatBots public override void Initialize() { //Load the given file from the startup parameters - if (LookForScript(ref file)) + if (LookForScript(ref file!)) { lines = System.IO.File.ReadAllLines(file, Encoding.UTF8); csharp = file.EndsWith(".cs"); @@ -145,7 +142,7 @@ namespace MinecraftClient.ChatBots if (!String.IsNullOrEmpty(owner)) SendPrivateMessage(owner, Translations.Get("bot.script.file_not_found", file)); - + UnloadBot(); //No need to keep the bot active } } @@ -171,8 +168,10 @@ namespace MinecraftClient.ChatBots SendPrivateMessage(owner, errorMessage); LogToConsole(e.InnerException); } - }); - thread.Name = "MCC Script - " + file; + }) + { + Name = "MCC Script - " + file + }; thread.Start(); } @@ -204,7 +203,7 @@ namespace MinecraftClient.ChatBots int ticks = 10; try { - ticks = Convert.ToInt32(instruction_line.Substring(5, instruction_line.Length - 5)); + ticks = Convert.ToInt32(instruction_line[5..]); } catch { } sleepticks = ticks; diff --git a/MinecraftClient/ChatBots/ScriptScheduler.cs b/MinecraftClient/ChatBots/ScriptScheduler.cs index 089d7946..b30bb468 100644 --- a/MinecraftClient/ChatBots/ScriptScheduler.cs +++ b/MinecraftClient/ChatBots/ScriptScheduler.cs @@ -1,8 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Globalization; +using System.Text; namespace MinecraftClient.ChatBots { @@ -14,7 +13,7 @@ namespace MinecraftClient.ChatBots { private class TaskDesc { - public string action = null; + public string? action = null; public bool triggerOnFirstLogin = false; public bool triggerOnLogin = false; public bool triggerOnTime = false; @@ -22,17 +21,17 @@ namespace MinecraftClient.ChatBots public int triggerOnInterval_Interval = 0; public int triggerOnInterval_Interval_Max = 0; public int triggerOnInterval_Interval_Countdown = 0; - public List triggerOnTime_Times = new List(); + public List triggerOnTime_Times = new(); public bool triggerOnTime_alreadyTriggered = false; } private static bool firstlogin_done = false; - private string tasksfile; + private readonly string tasksfile; private bool serverlogin_done; - private List tasks = new List(); + private readonly List tasks = new(); private int verifytasks_timeleft = 10; - private int verifytasks_delay = 10; + private readonly int verifytasks_delay = 10; public ScriptScheduler(string tasksfile) { @@ -46,19 +45,19 @@ namespace MinecraftClient.ChatBots if (System.IO.File.Exists(tasksfile)) { LogDebugToConsoleTranslated("bot.scriptScheduler.loading", System.IO.Path.GetFullPath(tasksfile)); - TaskDesc current_task = null; - String[] lines = System.IO.File.ReadAllLines(tasksfile, Encoding.UTF8); + TaskDesc? current_task = null; + string[] lines = System.IO.File.ReadAllLines(tasksfile, Encoding.UTF8); foreach (string lineRAW in lines) { string line = lineRAW.Split('#')[0].Trim(); if (line.Length > 0) { - if (line[0] == '[' && line[line.Length - 1] == ']') + if (line[0] == '[' && line[^1] == ']') { - switch (line.Substring(1, line.Length - 2).ToLower()) + switch (line[1..^1].ToLower()) { case "task": - checkAddTask(current_task); + CheckAddTask(current_task); current_task = new TaskDesc(); //Create a blank task break; } @@ -68,7 +67,7 @@ namespace MinecraftClient.ChatBots string argName = line.Split('=')[0]; if (line.Length > (argName.Length + 1)) { - string argValue = line.Substring(argName.Length + 1); + string argValue = line[(argName.Length + 1)..]; switch (argName.ToLower()) { case "triggeronfirstlogin": current_task.triggerOnFirstLogin = Settings.str2bool(argValue); break; @@ -77,21 +76,26 @@ namespace MinecraftClient.ChatBots case "triggeroninterval": current_task.triggerOnInterval = Settings.str2bool(argValue); break; case "timevalue": try { current_task.triggerOnTime_Times.Add(DateTime.ParseExact(argValue, "HH:mm", CultureInfo.InvariantCulture)); } catch { } break; case "timeinterval": - int interval = 1; + int interval; int intervalMax = 0; - if (argValue.Contains("-")) + if (argValue.Contains('-')) { string[] parts = argValue.Split("-"); - if (parts.Length == 2) { - int.TryParse(parts[0].Trim(), out interval); - int.TryParse(parts[1].Trim(), out intervalMax); + interval = int.Parse(parts[0].Trim()); + intervalMax = int.Parse(parts[1].Trim()); + } + else + { + interval = 1; } - else interval = 1; } - else int.TryParse(argValue, out interval); + else + { + interval = int.Parse(argValue); + } current_task.triggerOnInterval_Interval = interval; current_task.triggerOnInterval_Interval_Max = intervalMax; @@ -104,7 +108,7 @@ namespace MinecraftClient.ChatBots } } } - checkAddTask(current_task); + CheckAddTask(current_task); } else { @@ -113,7 +117,7 @@ namespace MinecraftClient.ChatBots } } - private void checkAddTask(TaskDesc current_task) + private void CheckAddTask(TaskDesc? current_task) { //Check if we built a valid task before adding it if (current_task != null) @@ -166,7 +170,7 @@ namespace MinecraftClient.ChatBots { task.triggerOnTime_alreadyTriggered = true; LogDebugToConsoleTranslated("bot.scriptScheduler.running_time", task.action); - PerformInternalCommand(task.action); + PerformInternalCommand(task.action!); } } } @@ -186,7 +190,7 @@ namespace MinecraftClient.ChatBots task.triggerOnInterval_Interval_Countdown = time; LogDebugToConsoleTranslated("bot.scriptScheduler.running_inverval", task.action); - PerformInternalCommand(task.action); + PerformInternalCommand(task.action!); } else task.triggerOnInterval_Interval_Countdown--; } @@ -199,7 +203,7 @@ namespace MinecraftClient.ChatBots if (task.triggerOnLogin || (firstlogin_done == false && task.triggerOnFirstLogin)) { LogDebugToConsoleTranslated("bot.scriptScheduler.running_login", task.action); - PerformInternalCommand(task.action); + PerformInternalCommand(task.action!); } } diff --git a/MinecraftClient/ChatBots/TestBot.cs b/MinecraftClient/ChatBots/TestBot.cs index c531e85b..b9ac86a2 100644 --- a/MinecraftClient/ChatBots/TestBot.cs +++ b/MinecraftClient/ChatBots/TestBot.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MinecraftClient.ChatBots +namespace MinecraftClient.ChatBots { /// /// Example of message receiving. diff --git a/MinecraftClient/Command.cs b/MinecraftClient/Command.cs index 62909f62..627542c6 100644 --- a/MinecraftClient/Command.cs +++ b/MinecraftClient/Command.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; namespace MinecraftClient @@ -50,12 +49,12 @@ namespace MinecraftClient /// Return a list of aliases for this command. /// Override this method if you wish to put aliases to the command /// - public virtual IEnumerable getCMDAliases() { return new string[0]; } + public virtual IEnumerable GetCMDAliases() { return Array.Empty(); } /// /// Check if at least one argument has been passed to the command /// - public static bool hasArg(string command) + public static bool HasArg(string command) { int first_space = command.IndexOf(' '); return (first_space > 0 && first_space < command.Length - 1); @@ -65,30 +64,25 @@ namespace MinecraftClient /// Extract the argument string from the command /// /// Argument or "" if no argument - public static string getArg(string command) + public static string GetArg(string command) { - if (hasArg(command)) - { - return command.Substring(command.IndexOf(' ') + 1); - } - else return ""; + if (HasArg(command)) + return command[(command.IndexOf(' ') + 1)..]; + else + return string.Empty; } /// /// Extract the arguments as a string array from the command /// /// Argument array or empty array if no arguments - public static string[] getArgs(string command) + public static string[] GetArgs(string command) { - string[] args = getArg(command).Split(' ', StringSplitOptions.RemoveEmptyEntries); - if (args.Length == 1 && args[0] == "") - { - return new string[] { }; - } + string[] args = GetArg(command).Split(' ', StringSplitOptions.RemoveEmptyEntries); + if (args.Length == 1 && args[0] == string.Empty) + return Array.Empty(); else - { return args; - } } /// @@ -97,7 +91,7 @@ namespace MinecraftClient /// /// Provided arguments as a string /// All extracted arguments in a string list - public static List parseCommandLine(string cmdLine) + public static List ParseCommandLine(string cmdLine) { var args = new List(); if (string.IsNullOrWhiteSpace(cmdLine)) return args; @@ -107,7 +101,7 @@ namespace MinecraftClient for (int i = 0; i < cmdLine.Length; i++) { - if ((cmdLine[i] == '"' && i > 0 && cmdLine[i-1] != '\\') || (cmdLine[i] == '"' && i == 0)) + if ((cmdLine[i] == '"' && i > 0 && cmdLine[i - 1] != '\\') || (cmdLine[i] == '"' && i == 0)) { if (inQuotedArg) { @@ -136,7 +130,7 @@ namespace MinecraftClient { if (cmdLine[i] == '\\' && cmdLine[i + 1] == '\"') { - currentArg.Append("\""); + currentArg.Append('"'); i += 1; } else diff --git a/MinecraftClient/Commands/Animation.cs b/MinecraftClient/Commands/Animation.cs index 463958f1..cdfa8ad7 100644 --- a/MinecraftClient/Commands/Animation.cs +++ b/MinecraftClient/Commands/Animation.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace MinecraftClient.Commands { @@ -11,11 +8,11 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "animation "; } } public override string CmdDesc { get { return "cmd.animation.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { - if (hasArg(command)) + if (HasArg(command)) { - string[] args = getArgs(command); + string[] args = GetArgs(command); if (args.Length > 0) { if (args[0] == "mainhand" || args[0] == "0") diff --git a/MinecraftClient/Commands/Bed.cs b/MinecraftClient/Commands/Bed.cs index 37936fd5..3bffd887 100644 --- a/MinecraftClient/Commands/Bed.cs +++ b/MinecraftClient/Commands/Bed.cs @@ -12,9 +12,9 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "bed leave|sleep |sleep "; } } public override string CmdDesc { get { return "cmd.bed.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { - string[] args = getArgs(command); + string[] args = GetArgs(command); if (args.Length >= 1) { diff --git a/MinecraftClient/Commands/ChangeSlot.cs b/MinecraftClient/Commands/ChangeSlot.cs index 814d75e9..f278cac7 100644 --- a/MinecraftClient/Commands/ChangeSlot.cs +++ b/MinecraftClient/Commands/ChangeSlot.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient.Commands { @@ -11,17 +9,17 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "changeslot <1-9>"; } } public override string CmdDesc { get { return "cmd.changeSlot.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { if (!handler.GetInventoryEnabled()) return Translations.Get("extra.inventory_required"); - if (hasArg(command)) + if (HasArg(command)) { short slot; try { - slot = Convert.ToInt16(getArg(command)); + slot = Convert.ToInt16(GetArg(command)); } catch (FormatException) { @@ -29,9 +27,9 @@ namespace MinecraftClient.Commands } if (slot >= 1 && slot <= 9) { - if (handler.ChangeSlot(slot-=1)) + if (handler.ChangeSlot(slot -= 1)) { - return Translations.Get("cmd.changeSlot.changed", (slot+=1)); + return Translations.Get("cmd.changeSlot.changed", (slot += 1)); } else { diff --git a/MinecraftClient/Commands/Chunk.cs b/MinecraftClient/Commands/Chunk.cs index ed876502..8939efc6 100644 --- a/MinecraftClient/Commands/Chunk.cs +++ b/MinecraftClient/Commands/Chunk.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; using MinecraftClient.Mapping; @@ -14,9 +13,9 @@ namespace MinecraftClient.Commands public override string Run(McClient handler, string command, Dictionary? localVars) { - if (hasArg(command)) + if (HasArg(command)) { - string[] args = getArgs(command); + string[] args = GetArgs(command); if (args.Length > 0) { if (args[0] == "status") @@ -29,7 +28,7 @@ namespace MinecraftClient.Commands StringBuilder sb = new(); - sb.Append(getChunkLoadingStatus(handler.GetWorld())); + sb.Append(World.GetChunkLoadingStatus(handler.GetWorld())); sb.Append('\n'); sb.Append(String.Format("Current location:{0}, chunk: ({1}, {2}).\n", current, current.ChunkX, current.ChunkZ)); @@ -135,7 +134,7 @@ namespace MinecraftClient.Commands // \ud83d\udd33: 🔳, \ud83d\udfe8: 🟨, \ud83d\udfe9: 🟩, \u25A1: □, \u25A3: ▣, \u25A0: ■ - string[] chunkStatusStr = Settings.EnableEmoji ? + string[] chunkStatusStr = Settings.EnableEmoji ? new string[] { "\ud83d\udd33", "\ud83d\udfe8", "\ud83d\udfe9" } : new string[] { "\u25A1", "\u25A3", "\u25A0" }; // Output @@ -177,7 +176,7 @@ namespace MinecraftClient.Commands ChunkColumn? chunkColumn = world[chunkX, chunkZ]; if (chunkColumn != null) chunkColumn.FullyLoaded = false; - return (chunkColumn == null) ? "Fail: chunk dosen't exist!" : + return (chunkColumn == null) ? "Fail: chunk dosen't exist!" : String.Format("Successfully marked chunk ({0}, {1}) as loading.", chunkX, chunkZ); } else @@ -194,7 +193,7 @@ namespace MinecraftClient.Commands ChunkColumn? chunkColumn = world[chunkX, chunkZ]; if (chunkColumn != null) chunkColumn.FullyLoaded = true; - return (chunkColumn == null) ? "Fail: chunk dosen't exist!" : + return (chunkColumn == null) ? "Fail: chunk dosen't exist!" : String.Format("Successfully marked chunk ({0}, {1}) as loaded.", chunkX, chunkZ); } else @@ -220,11 +219,11 @@ namespace MinecraftClient.Commands else return GetCmdDescTranslated(); } - else + else return GetCmdDescTranslated(); } - private Tuple? ParseChunkPos(string[] args) + private static Tuple? ParseChunkPos(string[] args) { try { @@ -249,19 +248,5 @@ namespace MinecraftClient.Commands return null; } } - - private string getChunkLoadingStatus(World world) - { - double chunkLoadedRatio; - if (world.chunkCnt == 0) - chunkLoadedRatio = 0; - else - chunkLoadedRatio = (world.chunkCnt - world.chunkLoadNotCompleted) / (double)world.chunkCnt; - - string status = Translations.Get("cmd.move.chunk_loading_status", - chunkLoadedRatio, world.chunkCnt - world.chunkLoadNotCompleted, world.chunkCnt); - - return status; - } } } diff --git a/MinecraftClient/Commands/Connect.cs b/MinecraftClient/Commands/Connect.cs index f8fac928..ca95c81a 100644 --- a/MinecraftClient/Commands/Connect.cs +++ b/MinecraftClient/Commands/Connect.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace MinecraftClient.Commands { @@ -11,11 +8,11 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "connect [account]"; } } public override string CmdDesc { get { return "cmd.connect.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient? handler, string command, Dictionary? localVars) { - if (hasArg(command)) + if (HasArg(command)) { - string[] args = getArgs(command); + string[] args = GetArgs(command); if (args.Length > 1) { if (!Settings.SetAccount(args[1])) diff --git a/MinecraftClient/Commands/Debug.cs b/MinecraftClient/Commands/Debug.cs index 11c122fc..c08404e0 100644 --- a/MinecraftClient/Commands/Debug.cs +++ b/MinecraftClient/Commands/Debug.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace MinecraftClient.Commands { @@ -11,11 +8,11 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "debug [on|off]"; } } public override string CmdDesc { get { return "cmd.debug.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { - if (hasArg(command)) + if (HasArg(command)) { - Settings.DebugMessages = (getArg(command).ToLower() == "on"); + Settings.DebugMessages = (GetArg(command).ToLower() == "on"); } else Settings.DebugMessages = !Settings.DebugMessages; return Translations.Get(Settings.DebugMessages ? "cmd.debug.state_on" : "cmd.debug.state_off"); diff --git a/MinecraftClient/Commands/Dig.cs b/MinecraftClient/Commands/Dig.cs index 6f297720..9438d1bc 100644 --- a/MinecraftClient/Commands/Dig.cs +++ b/MinecraftClient/Commands/Dig.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using MinecraftClient.Mapping; namespace MinecraftClient.Commands @@ -12,12 +10,12 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "dig "; } } public override string CmdDesc { get { return "cmd.dig.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { if (!handler.GetTerrainEnabled()) return Translations.Get("extra.terrainandmovement_required"); - string[] args = getArgs(command); + string[] args = GetArgs(command); if (args.Length == 0) { (bool hasBlock, Location blockLoc, Block block) = RaycastHelper.RaycastBlock(handler, 4.5, false); diff --git a/MinecraftClient/Commands/DropItem.cs b/MinecraftClient/Commands/DropItem.cs index db1da5e5..54f93254 100644 --- a/MinecraftClient/Commands/DropItem.cs +++ b/MinecraftClient/Commands/DropItem.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using MinecraftClient.Inventory; namespace MinecraftClient.Commands @@ -14,17 +13,16 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "/dropitem "; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { if (!handler.GetInventoryEnabled()) { return Translations.Get("extra.inventory_required"); } - if (hasArg(command)) + if (HasArg(command)) { - string arg = getArg(command); - ItemType itemType; - if (Enum.TryParse(arg, true, out itemType)) + string arg = GetArg(command); + if (Enum.TryParse(arg, true, out ItemType itemType)) { int inventoryId; var inventories = handler.GetInventories(); diff --git a/MinecraftClient/Commands/Entitycmd.cs b/MinecraftClient/Commands/Entitycmd.cs index 8aebdaf1..767f7134 100644 --- a/MinecraftClient/Commands/Entitycmd.cs +++ b/MinecraftClient/Commands/Entitycmd.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Drawing; using MinecraftClient.Inventory; using MinecraftClient.Mapping; @@ -12,17 +11,16 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "entity "; } } public override string CmdDesc { get { return ""; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { if (handler.GetEntityHandlingEnabled()) { - string[] args = getArgs(command); + string[] args = GetArgs(command); if (args.Length >= 1) { try { - int entityID = 0; - int.TryParse(args[0], out entityID); + int entityID = int.Parse(args[0]); if (entityID != 0) { if (handler.GetEntities().ContainsKey(entityID)) @@ -44,8 +42,8 @@ namespace MinecraftClient.Commands float health = entity.Health; int latency = entity.Latency; Item item = entity.Item; - string nickname = entity.Name; - string customname = entity.CustomName; + string? nickname = entity.Name; + string? customname = entity.CustomName; EntityPose pose = entity.Pose; EntityType type = entity.Type; double distance = Math.Round(entity.Location.Distance(handler.GetCurrentLocation()), 2); @@ -66,7 +64,7 @@ namespace MinecraftClient.Commands done += Translations.Replace("\n [MCC] ([cmd.entityCmd.latency]): {0}", latency); else if (type == EntityType.Item || type == EntityType.ItemFrame || type == Mapping.EntityType.EyeOfEnder || type == Mapping.EntityType.Egg || type == Mapping.EntityType.EnderPearl || type == Mapping.EntityType.Potion || type == Mapping.EntityType.Fireball || type == Mapping.EntityType.FireworkRocket) { - string displayName = item.DisplayName; + string? displayName = item.DisplayName; if (String.IsNullOrEmpty(displayName)) done += Translations.Replace("\n [MCC] ([cmd.entityCmd.item]): {0} x{1}", item.Type, item.Count); else @@ -100,8 +98,7 @@ namespace MinecraftClient.Commands } else { - EntityType interacttype = EntityType.Player; - Enum.TryParse(args[0], out interacttype); + EntityType interacttype = Enum.Parse(args[0]); string actionst = "cmd.entityCmd.attacked"; int actioncount = 0; foreach (var entity2 in handler.GetEntities()) @@ -134,15 +131,17 @@ namespace MinecraftClient.Commands else { Dictionary entities = handler.GetEntities(); - List response = new List(); - response.Add(Translations.Get("cmd.entityCmd.entities")); + List response = new() + { + Translations.Get("cmd.entityCmd.entities") + }; foreach (var entity2 in entities) { int id = entity2.Key; float health = entity2.Value.Health; int latency = entity2.Value.Latency; - string nickname = entity2.Value.Name; - string customname = entity2.Value.CustomName; + string? nickname = entity2.Value.Name; + string? customname = entity2.Value.CustomName; EntityPose pose = entity2.Value.Pose; EntityType type = entity2.Value.Type; Item item = entity2.Value.Item; diff --git a/MinecraftClient/Commands/ExecIf.cs b/MinecraftClient/Commands/ExecIf.cs index df2c9e37..474c1c50 100644 --- a/MinecraftClient/Commands/ExecIf.cs +++ b/MinecraftClient/Commands/ExecIf.cs @@ -11,11 +11,11 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "execif ---> "; } } public override string CmdDesc { get { return "cmd.execif.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { - if (hasArg(command)) + if (HasArg(command)) { - string commandsString = getArg(command); + string commandsString = GetArg(command); if (!commandsString.Contains("--->")) return GetCmdDescTranslated(); @@ -41,44 +41,41 @@ namespace MinecraftClient.Commands var result = interpreter.Eval(expressionText); - if (result != null) + bool shouldExec = result; + + /*if (result is bool) + shouldExec = (bool)result; + else if (result is string) + shouldExec = !string.IsNullOrEmpty((string)result) && ((string)result).Trim().Contains("true", StringComparison.OrdinalIgnoreCase); + else if (result is int) + shouldExec = (int)result > 0; + else if (result is double) + shouldExec = (double)result > 0; + else if (result is float) + shouldExec = (float)result > 0; + else if (result is Int16) + shouldExec = (Int16)result > 0; + else if (result is Int32) + shouldExec = (Int32)result > 0; + else if (result is Int64) + shouldExec = (Int64)result > 0; + */ + + handler.Log.Debug("[Execif] Result Type: " + result.GetType().Name); + + if (shouldExec) { - bool shouldExec = result; + string? output = ""; + handler.PerformInternalCommand(resultCommand, ref output); - /*if (result is bool) - shouldExec = (bool)result; - else if (result is string) - shouldExec = !string.IsNullOrEmpty((string)result) && ((string)result).Trim().Contains("true", StringComparison.OrdinalIgnoreCase); - else if (result is int) - shouldExec = (int)result > 0; - else if (result is double) - shouldExec = (double)result > 0; - else if (result is float) - shouldExec = (float)result > 0; - else if (result is Int16) - shouldExec = (Int16)result > 0; - else if (result is Int32) - shouldExec = (Int32)result > 0; - else if (result is Int64) - shouldExec = (Int64)result > 0; - */ - - handler.Log.Debug("[Execif] Result Type: " + result.GetType().Name); - - if (shouldExec) - { - string output = ""; - handler.PerformInternalCommand(resultCommand, ref output); - - if (string.IsNullOrEmpty(output)) - handler.Log.Debug(Translations.TryGet("cmd.execif.executed_no_output", expressionText, resultCommand)); - else handler.Log.Debug(Translations.TryGet("cmd.execif.executed", expressionText, resultCommand, output)); - - return ""; - } + if (string.IsNullOrEmpty(output)) + handler.Log.Debug(Translations.TryGet("cmd.execif.executed_no_output", expressionText, resultCommand)); + else handler.Log.Debug(Translations.TryGet("cmd.execif.executed", expressionText, resultCommand, output)); return ""; } + + return ""; } catch (Exception e) { @@ -86,8 +83,6 @@ namespace MinecraftClient.Commands handler.Log.Error(Translations.TryGet("cmd.execif.error", e.Message)); return ""; } - - return GetCmdDescTranslated(); } return GetCmdDescTranslated(); diff --git a/MinecraftClient/Commands/ExecMulti.cs b/MinecraftClient/Commands/ExecMulti.cs index a7ad217f..a329da10 100644 --- a/MinecraftClient/Commands/ExecMulti.cs +++ b/MinecraftClient/Commands/ExecMulti.cs @@ -10,11 +10,11 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "execmulti -> -> -> ..."; } } public override string CmdDesc { get { return "cmd.execmulti.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { - if (hasArg(command)) + if (HasArg(command)) { - string commandsString = getArg(command); + string commandsString = GetArg(command); if (commandsString.Contains("execmulti", StringComparison.OrdinalIgnoreCase) || commandsString.Contains("execif", StringComparison.OrdinalIgnoreCase)) return Translations.TryGet("cmd.execmulti.prevent"); @@ -25,16 +25,17 @@ namespace MinecraftClient.Commands foreach (string cmd in commands) { - string output = ""; + string? output = ""; handler.PerformInternalCommand(cmd, ref output); string log = Translations.TryGet( "cmd.execmulti.executed", cmd, string.IsNullOrEmpty(output) ? Translations.TryGet("cmd.execmulti.no_result") : Translations.TryGet("cmd.execmulti.result", output)); - if (output.Contains("unknown command", StringComparison.OrdinalIgnoreCase)) + if (output != null && output.Contains("unknown command", StringComparison.OrdinalIgnoreCase)) handler.Log.Error(log); - else handler.Log.Info(log); + else + handler.Log.Info(log); } return ""; diff --git a/MinecraftClient/Commands/Exit.cs b/MinecraftClient/Commands/Exit.cs index 8a442786..7bca6496 100644 --- a/MinecraftClient/Commands/Exit.cs +++ b/MinecraftClient/Commands/Exit.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace MinecraftClient.Commands { @@ -11,13 +8,13 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "exit"; } } public override string CmdDesc { get { return "cmd.exit.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient? handler, string command, Dictionary? localVars) { Program.Exit(); return ""; } - public override IEnumerable getCMDAliases() + public override IEnumerable GetCMDAliases() { return new string[] { "quit" }; } diff --git a/MinecraftClient/Commands/Health.cs b/MinecraftClient/Commands/Health.cs index 95e084c1..68af9b32 100644 --- a/MinecraftClient/Commands/Health.cs +++ b/MinecraftClient/Commands/Health.cs @@ -1,7 +1,4 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient.Commands { @@ -11,7 +8,7 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "health"; } } public override string CmdDesc { get { return "cmd.health.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { return Translations.Get("cmd.health.response", handler.GetHealth(), handler.GetSaturation(), handler.GetLevel(), handler.GetTotalExperience()); } diff --git a/MinecraftClient/Commands/Inventory.cs b/MinecraftClient/Commands/Inventory.cs index 5821df68..58d7997e 100644 --- a/MinecraftClient/Commands/Inventory.cs +++ b/MinecraftClient/Commands/Inventory.cs @@ -16,7 +16,7 @@ namespace MinecraftClient.Commands { if (handler.GetInventoryEnabled()) { - string[] args = getArgs(command); + string[] args = GetArgs(command); if (args.Length >= 1) { int inventoryId; @@ -117,7 +117,7 @@ namespace MinecraftClient.Commands { inventory.Items.Values .ToList() - .FindAll(item => item.Type == parsedItemType && (shouldUseItemCount ? item.Count == itemCount : true)) + .FindAll(item => item.Type == parsedItemType && (!shouldUseItemCount || item.Count == itemCount)) .ForEach(item => { if (!foundItems.ContainsKey(inventory.ID)) @@ -183,7 +183,7 @@ namespace MinecraftClient.Commands response.Append(Translations.Get("cmd.inventory.inventory")); response.AppendLine(String.Format(" #{0} - {1}§8", inventoryId, inventory.Title)); - string asciiArt = inventory.Type.GetAsciiArt(); + string? asciiArt = inventory.Type.GetAsciiArt(); if (asciiArt != null && Settings.DisplayInventoryLayout) response.AppendLine(asciiArt); diff --git a/MinecraftClient/Commands/List.cs b/MinecraftClient/Commands/List.cs index 7cc4575c..f261d670 100644 --- a/MinecraftClient/Commands/List.cs +++ b/MinecraftClient/Commands/List.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient.Commands { @@ -11,7 +9,7 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "list"; } } public override string CmdDesc { get { return "cmd.list.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { return Translations.Get("cmd.list.players", String.Join(", ", handler.GetOnlinePlayers())); } diff --git a/MinecraftClient/Commands/Log.cs b/MinecraftClient/Commands/Log.cs index 9c0daf1e..412e401b 100644 --- a/MinecraftClient/Commands/Log.cs +++ b/MinecraftClient/Commands/Log.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace MinecraftClient.Commands { @@ -11,11 +8,11 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "log "; } } public override string CmdDesc { get { return "cmd.log.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { - if (hasArg(command)) + if (HasArg(command)) { - ConsoleIO.WriteLogLine(getArg(command)); + ConsoleIO.WriteLogLine(GetArg(command)); return ""; } else return GetCmdDescTranslated(); diff --git a/MinecraftClient/Commands/Look.cs b/MinecraftClient/Commands/Look.cs index 433f53a7..2f6488b2 100644 --- a/MinecraftClient/Commands/Look.cs +++ b/MinecraftClient/Commands/Look.cs @@ -1,8 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Net.Http.Headers; -using System.Text; using MinecraftClient.Mapping; namespace MinecraftClient.Commands @@ -13,11 +10,11 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "look "; } } public override string CmdDesc { get { return "cmd.look.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { if (handler.GetTerrainEnabled()) { - string[] args = getArgs(command); + string[] args = GetArgs(command); if (args.Length == 0) { const double maxDistance = 8.0; @@ -33,7 +30,7 @@ namespace MinecraftClient.Commands } else if (args.Length == 1) { - string dirStr = getArg(command).Trim().ToLower(); + string dirStr = GetArg(command).Trim().ToLower(); Direction direction; switch (dirStr) { @@ -53,8 +50,8 @@ namespace MinecraftClient.Commands { try { - float yaw = Single.Parse(args[0]); - float pitch = Single.Parse(args[1]); + float yaw = float.Parse(args[0]); + float pitch = float.Parse(args[1]); handler.UpdateLocation(handler.GetCurrentLocation(), yaw, pitch); return Translations.Get("cmd.look.at", yaw.ToString("0.00"), pitch.ToString("0.00")); diff --git a/MinecraftClient/Commands/Move.cs b/MinecraftClient/Commands/Move.cs index edd95ccd..6bc6e1fb 100644 --- a/MinecraftClient/Commands/Move.cs +++ b/MinecraftClient/Commands/Move.cs @@ -11,9 +11,9 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "move [-f]"; } } public override string CmdDesc { get { return "walk or start walking. \"-f\": force unsafe movements like falling or touching fire"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { - List args = getArgs(command.ToLower()).ToList(); + List args = GetArgs(command.ToLower()).ToList(); bool takeRisk = false; if (args.Count < 1) @@ -21,7 +21,7 @@ namespace MinecraftClient.Commands string desc = GetCmdDescTranslated(); if (handler.GetTerrainEnabled()) - handler.Log.Info(getChunkLoadingStatus(handler.GetWorld())); + handler.Log.Info(World.GetChunkLoadingStatus(handler.GetWorld())); return desc; } @@ -65,7 +65,7 @@ namespace MinecraftClient.Commands case "south": direction = Direction.South; break; case "center": Location current = handler.GetCurrentLocation(); - Location currentCenter = new Location(Math.Floor(current.X) + 0.5, current.Y, Math.Floor(current.Z) + 0.5); + Location currentCenter = new(Math.Floor(current.X) + 0.5, current.Y, Math.Floor(current.Z) + 0.5); handler.MoveTo(currentCenter, allowDirectTeleport: true); return Translations.Get("cmd.move.walk", currentCenter, current); case "get": return handler.GetCurrentLocation().ToString(); @@ -81,7 +81,7 @@ namespace MinecraftClient.Commands { if (handler.MoveTo(goal, allowUnsafe: takeRisk)) return Translations.Get("cmd.move.moving", args[0]); - else + else return takeRisk ? Translations.Get("cmd.move.dir_fail") : Translations.Get("cmd.move.suggestforce"); } else return Translations.Get("cmd.move.dir_fail"); @@ -113,19 +113,5 @@ namespace MinecraftClient.Commands } else return Translations.Get("extra.terrainandmovement_required"); } - - private string getChunkLoadingStatus(World world) - { - double chunkLoadedRatio; - if (world.chunkCnt == 0) - chunkLoadedRatio = 0; - else - chunkLoadedRatio = (world.chunkCnt - world.chunkLoadNotCompleted) / (double)world.chunkCnt; - - string status = Translations.Get("cmd.move.chunk_loading_status", - chunkLoadedRatio, world.chunkCnt - world.chunkLoadNotCompleted, world.chunkCnt); - - return status; - } } } diff --git a/MinecraftClient/Commands/Reco.cs b/MinecraftClient/Commands/Reco.cs index 4119130c..46beebbb 100644 --- a/MinecraftClient/Commands/Reco.cs +++ b/MinecraftClient/Commands/Reco.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace MinecraftClient.Commands { @@ -11,9 +8,9 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "reco [account]"; } } public override string CmdDesc { get { return "cmd.reco.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient? handler, string command, Dictionary? localVars) { - string[] args = getArgs(command); + string[] args = GetArgs(command); if (args.Length > 0) { if (!Settings.SetAccount(args[0])) diff --git a/MinecraftClient/Commands/Respawn.cs b/MinecraftClient/Commands/Respawn.cs index aece669c..3ff718fd 100644 --- a/MinecraftClient/Commands/Respawn.cs +++ b/MinecraftClient/Commands/Respawn.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace MinecraftClient.Commands { @@ -11,7 +8,7 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "respawn"; } } public override string CmdDesc { get { return "cmd.respawn.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { handler.SendRespawnPacket(); return Translations.Get("cmd.respawn.done"); diff --git a/MinecraftClient/Commands/Script.cs b/MinecraftClient/Commands/Script.cs index 61145398..e7e233c5 100644 --- a/MinecraftClient/Commands/Script.cs +++ b/MinecraftClient/Commands/Script.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace MinecraftClient.Commands { @@ -11,11 +8,11 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "script "; } } public override string CmdDesc { get { return "cmd.script.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { - if (hasArg(command)) + if (HasArg(command)) { - handler.BotLoad(new ChatBots.Script(getArg(command), null, localVars)); + handler.BotLoad(new ChatBots.Script(GetArg(command), null, localVars)); return ""; } else return GetCmdDescTranslated(); diff --git a/MinecraftClient/Commands/Send.cs b/MinecraftClient/Commands/Send.cs index 945ec94d..55977740 100644 --- a/MinecraftClient/Commands/Send.cs +++ b/MinecraftClient/Commands/Send.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace MinecraftClient.Commands { @@ -11,11 +8,11 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "send "; } } public override string CmdDesc { get { return "cmd.send.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { - if (hasArg(command)) + if (HasArg(command)) { - handler.SendText(getArg(command)); + handler.SendText(GetArg(command)); return ""; } else return GetCmdDescTranslated(); diff --git a/MinecraftClient/Commands/Set.cs b/MinecraftClient/Commands/Set.cs index a58541c8..9f6ccd78 100644 --- a/MinecraftClient/Commands/Set.cs +++ b/MinecraftClient/Commands/Set.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace MinecraftClient.Commands { @@ -11,14 +8,14 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "set varname=value"; } } public override string CmdDesc { get { return "cmd.set.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { - if (hasArg(command)) + if (HasArg(command)) { - string[] temp = getArg(command).Split('='); + string[] temp = GetArg(command).Split('='); if (temp.Length > 1) { - if (Settings.SetVar(temp[0], getArg(command).Substring(temp[0].Length + 1))) + if (Settings.SetVar(temp[0], GetArg(command).Substring(temp[0].Length + 1))) { return ""; //Success } diff --git a/MinecraftClient/Commands/SetRnd.cs b/MinecraftClient/Commands/SetRnd.cs index ea4f0b84..6ee7bfb8 100644 --- a/MinecraftClient/Commands/SetRnd.cs +++ b/MinecraftClient/Commands/SetRnd.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Text; namespace MinecraftClient.Commands { @@ -9,16 +8,16 @@ namespace MinecraftClient.Commands public override string CmdName { get { return "setrnd"; } } public override string CmdUsage { get { return Translations.Get("cmd.setrnd.format"); } } public override string CmdDesc { get { return "cmd.setrnd.desc"; } } - private static readonly Random rand = new Random(); + private static readonly Random rand = new(); - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { - if (hasArg(command)) + if (HasArg(command)) { - string[] args = getArg(command).Split(' '); + string[] args = GetArg(command).Split(' '); - if (args.Length > 1) - { + if (args.Length > 1) + { // detect "to" keyword in string if (args.Length == 2 && args[1].Contains("to")) { @@ -28,7 +27,7 @@ namespace MinecraftClient.Commands // try to extract the two numbers from the string try { - num1 = Convert.ToInt32(args[1].Substring(0, args[1].IndexOf('t'))); + num1 = Convert.ToInt32(args[1][..args[1].IndexOf('t')]); num2 = Convert.ToInt32(args[1].Substring(args[1].IndexOf('o') + 1, args[1].Length - 1 - args[1].IndexOf('o'))); } catch (Exception) @@ -38,11 +37,7 @@ namespace MinecraftClient.Commands // switch the values if they were entered in the wrong way if (num2 < num1) - { - int temp = num1; - num1 = num2; - num2 = temp; - } + (num2, num1) = (num1, num2); // create a variable or set it to num1 <= varlue < num2 if (Settings.SetVar(args[0], rand.Next(num1, num2))) @@ -54,10 +49,10 @@ namespace MinecraftClient.Commands else { // extract all arguments of the command - string argString = command.Substring(8 + command.Split(' ')[1].Length); + string argString = command[(8 + command.Split(' ')[1].Length)..]; // process all arguments similar to regular terminals with quotes and escaping - List values = parseCommandLine(argString); + List values = ParseCommandLine(argString); // create a variable or set it to one of the values if (values.Count > 0 && Settings.SetVar(args[0], values[rand.Next(0, values.Count)])) diff --git a/MinecraftClient/Commands/Sneak.cs b/MinecraftClient/Commands/Sneak.cs index 1ba6a94a..1c8dbf17 100644 --- a/MinecraftClient/Commands/Sneak.cs +++ b/MinecraftClient/Commands/Sneak.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace MinecraftClient.Commands { @@ -12,14 +9,14 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "Sneak"; } } public override string CmdDesc { get { return "cmd.sneak.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { if (sneaking) { var result = handler.SendEntityAction(Protocol.EntityActionType.StopSneaking); if (result) sneaking = false; - return Translations.Get(result ? "cmd.sneak.off" : "general.fail"); + return Translations.Get(result ? "cmd.sneak.off" : "general.fail"); } else { @@ -28,7 +25,6 @@ namespace MinecraftClient.Commands sneaking = true; return Translations.Get(result ? "cmd.sneak.on" : "general.fail"); } - } } } \ No newline at end of file diff --git a/MinecraftClient/Commands/Tps.cs b/MinecraftClient/Commands/Tps.cs index 356eb752..9aaafc5c 100644 --- a/MinecraftClient/Commands/Tps.cs +++ b/MinecraftClient/Commands/Tps.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient.Commands { @@ -11,7 +9,7 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "tps"; } } public override string CmdDesc { get { return "cmd.tps.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { var tps = Math.Round(handler.GetServerTPS(), 2); string color; @@ -19,7 +17,8 @@ namespace MinecraftClient.Commands color = "§c"; // Red else if (tps < 15) color = "§e"; // Yellow - else color = "§a"; // Green + else + color = "§a"; // Green return Translations.Get("cmd.tps.current") + ": " + color + tps; } } diff --git a/MinecraftClient/Commands/UseItem.cs b/MinecraftClient/Commands/UseItem.cs index c2ffa966..497633d2 100644 --- a/MinecraftClient/Commands/UseItem.cs +++ b/MinecraftClient/Commands/UseItem.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace MinecraftClient.Commands { @@ -11,7 +8,7 @@ namespace MinecraftClient.Commands public override string CmdUsage { get { return "useitem"; } } public override string CmdDesc { get { return "cmd.useitem.desc"; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { if (handler.GetInventoryEnabled()) { diff --git a/MinecraftClient/Commands/Useblock.cs b/MinecraftClient/Commands/Useblock.cs index f35ac385..05284afd 100644 --- a/MinecraftClient/Commands/Useblock.cs +++ b/MinecraftClient/Commands/Useblock.cs @@ -1,8 +1,5 @@ -using MinecraftClient.Mapping; -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; +using MinecraftClient.Mapping; namespace MinecraftClient.Commands { @@ -16,9 +13,9 @@ namespace MinecraftClient.Commands { if (!handler.GetTerrainEnabled()) return Translations.Get("extra.terrainandmovement_required"); - else if (hasArg(command)) + else if (HasArg(command)) { - string[] args = getArgs(command); + string[] args = GetArgs(command); if (args.Length >= 3) { Location block = Location.Parse(handler.GetCurrentLocation(), args[0], args[1], args[2]).ToFloor(); diff --git a/MinecraftClient/ConsoleIO.cs b/MinecraftClient/ConsoleIO.cs index a1f06d1d..13b55989 100644 --- a/MinecraftClient/ConsoleIO.cs +++ b/MinecraftClient/ConsoleIO.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Threading; namespace MinecraftClient { @@ -14,7 +12,7 @@ namespace MinecraftClient /// public static class ConsoleIO { - private static IAutoComplete autocomplete_engine; + private static IAutoComplete? autocomplete_engine; /// /// Reset the IO mechanism and clear all buffers @@ -77,8 +75,8 @@ namespace MinecraftClient public static string ReadLine() { if (BasicIO) - return Console.ReadLine(); - else + return Console.ReadLine() ?? String.Empty; + else return ConsoleInteractive.ConsoleReader.RequestImmediateInput(); } @@ -87,7 +85,7 @@ namespace MinecraftClient /// public static void DebugReadInput() { - ConsoleKeyInfo k = new ConsoleKeyInfo(); + ConsoleKeyInfo k; while (true) { k = Console.ReadKey(true); @@ -119,14 +117,11 @@ namespace MinecraftClient /// public static void WriteLineFormatted(string str, bool acceptnewlines = false, bool? displayTimestamp = null) { - StringBuilder output = new StringBuilder(); - + StringBuilder output = new(); + if (!String.IsNullOrEmpty(str)) { - if (displayTimestamp == null) - { - displayTimestamp = EnableTimestamps; - } + displayTimestamp ??= EnableTimestamps; if (displayTimestamp.Value) { int hour = DateTime.Now.Hour, minute = DateTime.Now.Minute, second = DateTime.Now.Second; @@ -183,10 +178,10 @@ namespace MinecraftClient public static void AutocompleteHandler(object? sender, ConsoleKey e) { if (e != ConsoleKey.Tab) return; - + if (autocomplete_engine == null) return; - + var buffer = ConsoleInteractive.ConsoleReader.GetBufferContent(); autocomplete_engine.AutoComplete(buffer.Text[..buffer.CursorPosition]); } diff --git a/MinecraftClient/Crypto/AesCfb8Stream.cs b/MinecraftClient/Crypto/AesCfb8Stream.cs index aac0443d..f653546c 100644 --- a/MinecraftClient/Crypto/AesCfb8Stream.cs +++ b/MinecraftClient/Crypto/AesCfb8Stream.cs @@ -1,12 +1,9 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Security.Cryptography; -using System.IO; using System.Collections.Concurrent; +using System.IO; using System.Runtime.CompilerServices; +using System.Security.Cryptography; +using System.Threading.Tasks; namespace MinecraftClient.Crypto { @@ -19,8 +16,8 @@ namespace MinecraftClient.Crypto private bool inStreamEnded = false; - private byte[] ReadStreamIV = new byte[16]; - private byte[] WriteStreamIV = new byte[16]; + private readonly byte[] ReadStreamIV = new byte[16]; + private readonly byte[] WriteStreamIV = new byte[16]; public Stream BaseStream { get; set; } diff --git a/MinecraftClient/Crypto/CryptoHandler.cs b/MinecraftClient/Crypto/CryptoHandler.cs index 5728835a..963c5dbc 100644 --- a/MinecraftClient/Crypto/CryptoHandler.cs +++ b/MinecraftClient/Crypto/CryptoHandler.cs @@ -1,9 +1,7 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Security.Cryptography; -using System.IO; +using System.Text; namespace MinecraftClient.Crypto { @@ -13,7 +11,7 @@ namespace MinecraftClient.Crypto public static class CryptoHandler { - public static byte[]? ClientAESPrivateKey = null; + public static byte[]? ClientAESPrivateKey; /// /// Get a cryptographic service for encrypting data using the server's RSA public key @@ -21,21 +19,21 @@ namespace MinecraftClient.Crypto /// Byte array containing the encoded key /// Returns the corresponding RSA Crypto Service - public static RSACryptoServiceProvider DecodeRSAPublicKey(byte[] x509key) + public static RSACryptoServiceProvider? DecodeRSAPublicKey(byte[] x509key) { /* Code from StackOverflow no. 18091460 */ byte[] SeqOID = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01 }; - System.IO.MemoryStream ms = new System.IO.MemoryStream(x509key); - System.IO.BinaryReader reader = new System.IO.BinaryReader(ms); + System.IO.MemoryStream ms = new(x509key); + System.IO.BinaryReader reader = new(ms); if (reader.ReadByte() == 0x30) ReadASNLength(reader); //skip the size else return null; - int identifierSize = 0; //total length of Object Identifier section + int identifierSize; //total length of Object Identifier section if (reader.ReadByte() == 0x30) identifierSize = ReadASNLength(reader); else @@ -78,10 +76,12 @@ namespace MinecraftClient.Crypto byte[] exponent = new byte[exponentSize]; reader.Read(exponent, 0, exponent.Length); - RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); - RSAParameters RSAKeyInfo = new RSAParameters(); - RSAKeyInfo.Modulus = modulus; - RSAKeyInfo.Exponent = exponent; + RSACryptoServiceProvider RSA = new(); + RSAParameters RSAKeyInfo = new() + { + Modulus = modulus, + Exponent = exponent + }; RSA.ImportParameters(RSAKeyInfo); return RSA; } @@ -120,8 +120,9 @@ namespace MinecraftClient.Crypto public static byte[] GenerateAESPrivateKey() { - AesManaged AES = new AesManaged(); - AES.KeySize = 128; AES.GenerateKey(); + Aes AES = Aes.Create(); + AES.KeySize = 128; + AES.GenerateKey(); return AES.Key; } @@ -133,9 +134,9 @@ namespace MinecraftClient.Crypto /// Secret key chosen by the client /// Returns the corresponding SHA-1 hex hash - public static string getServerHash(string serverID, byte[] PublicKey, byte[] SecretKey) + public static string GetServerHash(string serverID, byte[] PublicKey, byte[] SecretKey) { - byte[] hash = digest(new byte[][] { Encoding.GetEncoding("iso-8859-1").GetBytes(serverID), SecretKey, PublicKey }); + byte[] hash = Digest(new byte[][] { Encoding.GetEncoding("iso-8859-1").GetBytes(serverID), SecretKey, PublicKey }); bool negative = (hash[0] & 0x80) == 0x80; if (negative) { hash = TwosComplementLittleEndian(hash); } string result = GetHexString(hash).TrimStart('0'); @@ -149,13 +150,13 @@ namespace MinecraftClient.Crypto /// array of byte arrays to hash /// Returns the hashed data - private static byte[] digest(byte[][] tohash) + private static byte[] Digest(byte[][] tohash) { - SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); + SHA1 sha1 = SHA1.Create(); for (int i = 0; i < tohash.Length; i++) sha1.TransformBlock(tohash[i], 0, tohash[i].Length, tohash[i], 0); - sha1.TransformFinalBlock(new byte[] { }, 0, 0); - return sha1.Hash; + sha1.TransformFinalBlock(Array.Empty(), 0, 0); + return sha1.Hash!; } /// diff --git a/MinecraftClient/FileMonitor.cs b/MinecraftClient/FileMonitor.cs index 23c29b8e..378bb6b6 100644 --- a/MinecraftClient/FileMonitor.cs +++ b/MinecraftClient/FileMonitor.cs @@ -11,8 +11,8 @@ namespace MinecraftClient /// public class FileMonitor : IDisposable { - private Tuple? monitor = null; - private Tuple? polling = null; + private readonly Tuple? monitor = null; + private readonly Tuple? polling = null; /// /// Create a new FileMonitor and start monitoring @@ -24,7 +24,7 @@ namespace MinecraftClient { if (Settings.DebugMessages) { - string callerClass = new System.Diagnostics.StackFrame(1).GetMethod().DeclaringType.Name; + string callerClass = new System.Diagnostics.StackFrame(1).GetMethod()!.DeclaringType!.Name; ConsoleIO.WriteLineFormatted(Translations.Get("filemonitor.init", callerClass, Path.Combine(folder, filename))); } @@ -42,14 +42,14 @@ namespace MinecraftClient { if (Settings.DebugMessages) { - string callerClass = new System.Diagnostics.StackFrame(1).GetMethod().DeclaringType.Name; + string callerClass = new System.Diagnostics.StackFrame(1).GetMethod()!.DeclaringType!.Name; ConsoleIO.WriteLineFormatted(Translations.Get("filemonitor.fail", callerClass)); } monitor = null; var cancellationTokenSource = new CancellationTokenSource(); polling = new Tuple(new Thread(() => PollingThread(folder, filename, handler, cancellationTokenSource.Token)), cancellationTokenSource); - polling.Item1.Name = String.Format("{0} Polling thread: {1}", this.GetType().Name, Path.Combine(folder, filename)); + polling.Item1.Name = String.Format("{0} Polling thread: {1}", GetType().Name, Path.Combine(folder, filename)); polling.Item1.Start(); } } @@ -94,7 +94,7 @@ namespace MinecraftClient /// Last write time, or DateTime.MinValue if the file does not exist private DateTime GetLastWrite(string path) { - FileInfo fileInfo = new FileInfo(path); + FileInfo fileInfo = new(path); if (fileInfo.Exists) { return fileInfo.LastWriteTime; @@ -110,11 +110,10 @@ namespace MinecraftClient /// Encoding (default is UTF8) /// Thrown when failing to read the file despite multiple retries /// All lines - public static string[] ReadAllLinesWithRetries(string filePath, int maxTries = 3, Encoding encoding = null) + public static string[] ReadAllLinesWithRetries(string filePath, int maxTries = 3, Encoding? encoding = null) { int attempt = 0; - if (encoding == null) - encoding = Encoding.UTF8; + encoding ??= Encoding.UTF8; while (true) { try @@ -138,11 +137,10 @@ namespace MinecraftClient /// The lines to write to the file /// Maximum read attempts /// Encoding (default is UTF8) - public static void WriteAllLinesWithRetries(string filePath, IEnumerable lines, int maxTries = 3, Encoding encoding = null) + public static void WriteAllLinesWithRetries(string filePath, IEnumerable lines, int maxTries = 3, Encoding? encoding = null) { int attempt = 0; - if (encoding == null) - encoding = Encoding.UTF8; + encoding ??= Encoding.UTF8; while (true) { try diff --git a/MinecraftClient/INIFile.cs b/MinecraftClient/INIFile.cs index 712bc205..2dd8c719 100644 --- a/MinecraftClient/INIFile.cs +++ b/MinecraftClient/INIFile.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Text; namespace MinecraftClient @@ -42,9 +41,9 @@ namespace MinecraftClient string line = lineRaw.Split('#')[0].Trim(); if (line.Length > 0 && line[0] != ';') { - if (line[0] == '[' && line[line.Length - 1] == ']') + if (line[0] == '[' && line[^1] == ']') { - iniSection = line.Substring(1, line.Length - 2); + iniSection = line[1..^1]; if (lowerCase) iniSection = iniSection.ToLower(); } @@ -55,7 +54,7 @@ namespace MinecraftClient argName = argName.ToLower(); if (line.Length > (argName.Length + 1)) { - string argValue = line.Substring(argName.Length + 1); + string argValue = line[(argName.Length + 1)..]; if (!iniContents.ContainsKey(iniSection)) iniContents[iniSection] = new Dictionary(); iniContents[iniSection][argName] = argValue; @@ -73,7 +72,7 @@ namespace MinecraftClient /// Data to put into the file /// INI file description, inserted as a comment on first line of the INI file /// Automatically change first char of section and keys to uppercase - public static void WriteFile(string iniFile, Dictionary> contents, string description = null, bool autoCase = true) + public static void WriteFile(string iniFile, Dictionary> contents, string? description = null, bool autoCase = true) { File.WriteAllLines(iniFile, Generate(contents, description, autoCase), Encoding.UTF8); } @@ -85,9 +84,9 @@ namespace MinecraftClient /// INI file description, inserted as a comment on first line of the INI file /// Automatically change first char of section and keys to uppercase /// Lines of the INI file - public static string[] Generate(Dictionary> contents, string description = null, bool autoCase = true) + public static string[] Generate(Dictionary> contents, string? description = null, bool autoCase = true) { - List lines = new List(); + List lines = new(); if (!String.IsNullOrWhiteSpace(description)) lines.Add('#' + description); foreach (var section in contents) @@ -96,10 +95,10 @@ namespace MinecraftClient lines.Add(""); if (!String.IsNullOrEmpty(section.Key)) { - lines.Add("[" + (autoCase ? char.ToUpper(section.Key[0]) + section.Key.Substring(1) : section.Key) + ']'); + lines.Add("[" + (autoCase ? char.ToUpper(section.Key[0]) + section.Key[1..] : section.Key) + ']'); foreach (var item in section.Value) if (!String.IsNullOrEmpty(item.Key)) - lines.Add((autoCase ? char.ToUpper(item.Key[0]) + item.Key.Substring(1) : item.Key) + '=' + item.Value); + lines.Add((autoCase ? char.ToUpper(item.Key[0]) + item.Key[1..] : item.Key) + '=' + item.Value); } } return lines.ToArray(); diff --git a/MinecraftClient/Inventory/Container.cs b/MinecraftClient/Inventory/Container.cs index b39892b6..35a438b3 100644 --- a/MinecraftClient/Inventory/Container.cs +++ b/MinecraftClient/Inventory/Container.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace MinecraftClient.Inventory { @@ -23,7 +20,7 @@ namespace MinecraftClient.Inventory /// /// title of container /// - public string Title; + public string? Title; /// /// state of container @@ -35,11 +32,6 @@ namespace MinecraftClient.Inventory /// public Dictionary Items; - /// - /// Create an empty container - /// - public Container() { } - /// /// Create an empty container with ID, Type and Title /// @@ -61,7 +53,7 @@ namespace MinecraftClient.Inventory /// Container Type /// Container Title /// Container Items (key: slot ID, value: item info) - public Container(int id, ContainerType type, string title, Dictionary items) + public Container(int id, ContainerType type, string? title, Dictionary items) { ID = id; Type = type; @@ -130,33 +122,33 @@ namespace MinecraftClient.Inventory public static ContainerType GetContainerType(int typeID) { // https://wiki.vg/Inventory didn't state the inventory ID, assume that list start with 0 - switch (typeID) + return typeID switch { - case 0: return ContainerType.Generic_9x1; - case 1: return ContainerType.Generic_9x2; - case 2: return ContainerType.Generic_9x3; - case 3: return ContainerType.Generic_9x4; - case 4: return ContainerType.Generic_9x5; - case 5: return ContainerType.Generic_9x6; - case 6: return ContainerType.Generic_3x3; - case 7: return ContainerType.Anvil; - case 8: return ContainerType.Beacon; - case 9: return ContainerType.BlastFurnace; - case 10: return ContainerType.BrewingStand; - case 11: return ContainerType.Crafting; - case 12: return ContainerType.Enchantment; - case 13: return ContainerType.Furnace; - case 14: return ContainerType.Grindstone; - case 15: return ContainerType.Hopper; - case 16: return ContainerType.Lectern; - case 17: return ContainerType.Loom; - case 18: return ContainerType.Merchant; - case 19: return ContainerType.ShulkerBox; - case 20: return ContainerType.Smoker; - case 21: return ContainerType.Cartography; - case 22: return ContainerType.Stonecutter; - default: return ContainerType.Unknown; - } + 0 => ContainerType.Generic_9x1, + 1 => ContainerType.Generic_9x2, + 2 => ContainerType.Generic_9x3, + 3 => ContainerType.Generic_9x4, + 4 => ContainerType.Generic_9x5, + 5 => ContainerType.Generic_9x6, + 6 => ContainerType.Generic_3x3, + 7 => ContainerType.Anvil, + 8 => ContainerType.Beacon, + 9 => ContainerType.BlastFurnace, + 10 => ContainerType.BrewingStand, + 11 => ContainerType.Crafting, + 12 => ContainerType.Enchantment, + 13 => ContainerType.Furnace, + 14 => ContainerType.Grindstone, + 15 => ContainerType.Hopper, + 16 => ContainerType.Lectern, + 17 => ContainerType.Loom, + 18 => ContainerType.Merchant, + 19 => ContainerType.ShulkerBox, + 20 => ContainerType.Smoker, + 21 => ContainerType.Cartography, + 22 => ContainerType.Stonecutter, + _ => ContainerType.Unknown, + }; } /// @@ -166,7 +158,7 @@ namespace MinecraftClient.Inventory /// An array of slot ID public int[] SearchItem(ItemType itemType) { - List result = new List(); + List result = new(); if (Items != null) { foreach (var item in Items) @@ -185,7 +177,7 @@ namespace MinecraftClient.Inventory /// Also depending on the container type, some empty slots cannot be used e.g. armor slots. This might cause issues. public int[] GetEmpytSlots() { - List result = new List(); + List result = new(); for (int i = 0; i < Type.SlotCount(); i++) { result.Add(i); diff --git a/MinecraftClient/Inventory/ContainerType.cs b/MinecraftClient/Inventory/ContainerType.cs index 1bb101d6..76d05416 100644 --- a/MinecraftClient/Inventory/ContainerType.cs +++ b/MinecraftClient/Inventory/ContainerType.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MinecraftClient.Inventory +namespace MinecraftClient.Inventory { // For MC 1.14 after ONLY public enum ContainerType @@ -57,22 +52,24 @@ namespace MinecraftClient.Inventory { public static ContainerType ToNew(ContainerTypeOld type) { - switch (type) + return type switch { - case ContainerTypeOld.CONTAINER: return ContainerType.Unknown; - case ContainerTypeOld.CHEST: return ContainerType.Generic_9x3; - case ContainerTypeOld.CRAFTING_TABLE: return ContainerType.Crafting; - case ContainerTypeOld.FURNACE: return ContainerType.Furnace; - case ContainerTypeOld.DISPENSER: return ContainerType.Generic_3x3; - case ContainerTypeOld.ENCHANTING_TABLE: return ContainerType.Enchantment; - case ContainerTypeOld.BREWING_STAND: return ContainerType.BrewingStand; - case ContainerTypeOld.VILLAGER: return ContainerType.Merchant; - case ContainerTypeOld.HOPPER: return ContainerType.Hopper; - case ContainerTypeOld.DROPPER: return ContainerType.Generic_3x3; - case ContainerTypeOld.SHULKER_BOX: return ContainerType.ShulkerBox; - case ContainerTypeOld.ENTITYHORSE: return ContainerType.Unknown; - default: return ContainerType.Unknown; - } +#pragma warning disable format // @formatter:off + ContainerTypeOld.CONTAINER => ContainerType.Unknown, + ContainerTypeOld.CHEST => ContainerType.Generic_9x3, + ContainerTypeOld.CRAFTING_TABLE => ContainerType.Crafting, + ContainerTypeOld.FURNACE => ContainerType.Furnace, + ContainerTypeOld.DISPENSER => ContainerType.Generic_3x3, + ContainerTypeOld.ENCHANTING_TABLE => ContainerType.Enchantment, + ContainerTypeOld.BREWING_STAND => ContainerType.BrewingStand, + ContainerTypeOld.VILLAGER => ContainerType.Merchant, + ContainerTypeOld.HOPPER => ContainerType.Hopper, + ContainerTypeOld.DROPPER => ContainerType.Generic_3x3, + ContainerTypeOld.SHULKER_BOX => ContainerType.ShulkerBox, + ContainerTypeOld.ENTITYHORSE => ContainerType.Unknown, + _ => ContainerType.Unknown, +#pragma warning restore format // @formatter:on + }; } } } diff --git a/MinecraftClient/Inventory/ContainerTypeExtensions.cs b/MinecraftClient/Inventory/ContainerTypeExtensions.cs index 373bbb15..166693e9 100644 --- a/MinecraftClient/Inventory/ContainerTypeExtensions.cs +++ b/MinecraftClient/Inventory/ContainerTypeExtensions.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MinecraftClient.Inventory +namespace MinecraftClient.Inventory { public static class ContainerTypeExtensions { @@ -14,31 +9,33 @@ namespace MinecraftClient.Inventory /// Slot count of the container public static int SlotCount(this ContainerType c) { - switch (c) + return c switch { - case ContainerType.PlayerInventory: return 46; - case ContainerType.Generic_9x3: return 63; - case ContainerType.Generic_9x6: return 90; - case ContainerType.Generic_3x3: return 45; - case ContainerType.Crafting: return 46; - case ContainerType.BlastFurnace: return 39; - case ContainerType.Furnace: return 39; - case ContainerType.Smoker: return 39; - case ContainerType.Enchantment: return 38; - case ContainerType.BrewingStand: return 41; - case ContainerType.Merchant: return 39; - case ContainerType.Beacon: return 37; - case ContainerType.Anvil: return 39; - case ContainerType.Hopper: return 41; - case ContainerType.ShulkerBox: return 63; - case ContainerType.Loom: return 40; - case ContainerType.Stonecutter: return 38; - case ContainerType.Lectern: return 37; - case ContainerType.Cartography: return 39; - case ContainerType.Grindstone: return 39; - case ContainerType.Unknown: return 0; - default: return 0; - } +#pragma warning disable format // @formatter:off + ContainerType.PlayerInventory => 46, + ContainerType.Generic_9x3 => 63, + ContainerType.Generic_9x6 => 90, + ContainerType.Generic_3x3 => 45, + ContainerType.Crafting => 46, + ContainerType.BlastFurnace => 39, + ContainerType.Furnace => 39, + ContainerType.Smoker => 39, + ContainerType.Enchantment => 38, + ContainerType.BrewingStand => 41, + ContainerType.Merchant => 39, + ContainerType.Beacon => 37, + ContainerType.Anvil => 39, + ContainerType.Hopper => 41, + ContainerType.ShulkerBox => 63, + ContainerType.Loom => 40, + ContainerType.Stonecutter => 38, + ContainerType.Lectern => 37, + ContainerType.Cartography => 39, + ContainerType.Grindstone => 39, + ContainerType.Unknown => 0, + _ => 0, +#pragma warning restore format // @formatter:on + }; } /// @@ -46,33 +43,40 @@ namespace MinecraftClient.Inventory /// /// /// ASCII art representation or NULL if not implemented for this container type - public static string GetAsciiArt(this ContainerType c) + public static string? GetAsciiArt(this ContainerType c) { - switch (c) + return c switch { - case ContainerType.PlayerInventory: return DefaultConfigResource.ContainerType_PlayerInventory; - case ContainerType.Generic_9x3: return DefaultConfigResource.ContainerType_Generic_9x3; - case ContainerType.Generic_9x6: return DefaultConfigResource.ContainerType_Generic_9x6; - case ContainerType.Generic_3x3: return DefaultConfigResource.ContainerType_Generic_3x3; - case ContainerType.Crafting: return DefaultConfigResource.ContainerType_Crafting; - case ContainerType.BlastFurnace: return DefaultConfigResource.ContainerType_Furnace; - case ContainerType.Furnace: return DefaultConfigResource.ContainerType_Furnace; - case ContainerType.Smoker: return DefaultConfigResource.ContainerType_Furnace; - case ContainerType.Enchantment: return null; - case ContainerType.BrewingStand: return DefaultConfigResource.ContainerType_BrewingStand; - case ContainerType.Merchant: return null; - case ContainerType.Beacon: return null; - case ContainerType.Anvil: return null; - case ContainerType.Hopper: return DefaultConfigResource.ContainerType_Hopper; - case ContainerType.ShulkerBox: return DefaultConfigResource.ContainerType_Generic_9x3; - case ContainerType.Loom: return null; - case ContainerType.Stonecutter: return null; - case ContainerType.Lectern: return null; - case ContainerType.Cartography: return null; - case ContainerType.Grindstone: return DefaultConfigResource.ContainerType_Grindstone; - case ContainerType.Unknown: return null; - default: return null; - } +#pragma warning disable format // @formatter:off + ContainerType.PlayerInventory => DefaultConfigResource.ContainerType_PlayerInventory, + ContainerType.Generic_9x3 => DefaultConfigResource.ContainerType_Generic_9x3, + ContainerType.Generic_9x6 => DefaultConfigResource.ContainerType_Generic_9x6, + ContainerType.Generic_3x3 => DefaultConfigResource.ContainerType_Generic_3x3, + ContainerType.Crafting => DefaultConfigResource.ContainerType_Crafting, + ContainerType.BlastFurnace => DefaultConfigResource.ContainerType_Furnace, + ContainerType.Furnace => DefaultConfigResource.ContainerType_Furnace, + ContainerType.Smoker => DefaultConfigResource.ContainerType_Furnace, + ContainerType.Enchantment => null, + ContainerType.BrewingStand => DefaultConfigResource.ContainerType_BrewingStand, + ContainerType.Merchant => null, + ContainerType.Beacon => null, + ContainerType.Anvil => null, + ContainerType.Hopper => DefaultConfigResource.ContainerType_Hopper, + ContainerType.ShulkerBox => DefaultConfigResource.ContainerType_Generic_9x3, + ContainerType.Loom => null, + ContainerType.Stonecutter => null, + ContainerType.Lectern => null, + ContainerType.Cartography => null, + ContainerType.Grindstone => DefaultConfigResource.ContainerType_Grindstone, + ContainerType.Unknown => null, + ContainerType.Generic_9x1 => null, + ContainerType.Generic_9x2 => null, + ContainerType.Generic_9x4 => null, + ContainerType.Generic_9x5 => null, + ContainerType.SmightingTable => null, + _ => null, +#pragma warning restore format // @formatter:on + }; } } } diff --git a/MinecraftClient/Inventory/Effects.cs b/MinecraftClient/Inventory/Effects.cs index a5f3c194..5ab62ee4 100644 --- a/MinecraftClient/Inventory/Effects.cs +++ b/MinecraftClient/Inventory/Effects.cs @@ -1,9 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - namespace MinecraftClient.Inventory { /// diff --git a/MinecraftClient/Inventory/Item.cs b/MinecraftClient/Inventory/Item.cs index 628c4936..cfe4201e 100644 --- a/MinecraftClient/Inventory/Item.cs +++ b/MinecraftClient/Inventory/Item.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; +using System.Linq; namespace MinecraftClient.Inventory { @@ -33,9 +33,9 @@ namespace MinecraftClient.Inventory /// Item Metadata public Item(ItemType itemType, int count, Dictionary? nbt) { - this.Type = itemType; - this.Count = count; - this.NBT = nbt; + Type = itemType; + Count = count; + NBT = nbt; } /// @@ -53,50 +53,46 @@ namespace MinecraftClient.Inventory /// /// Retrieve item display name from NBT properties. NULL if no display name is defined. /// - public string DisplayName + public string? DisplayName { get { if (NBT != null && NBT.ContainsKey("display")) { - var displayProperties = NBT["display"] as Dictionary; - if (displayProperties != null && displayProperties.ContainsKey("Name")) + if (NBT["display"] is Dictionary displayProperties && displayProperties.ContainsKey("Name")) { - string displayName = displayProperties["Name"] as string; + string? displayName = displayProperties["Name"] as string; if (!String.IsNullOrEmpty(displayName)) - return MinecraftClient.Protocol.ChatParser.ParseText(displayProperties["Name"].ToString()); + return MinecraftClient.Protocol.ChatParser.ParseText(displayProperties["Name"].ToString() ?? string.Empty); } } return null; } } - + /// /// Retrieve item lores from NBT properties. Returns null if no lores is defined. /// - public string[] Lores + public string[]? Lores { get { - List lores = new List(); + List lores = new(); if (NBT != null && NBT.ContainsKey("display")) { - var displayProperties = NBT["display"] as Dictionary; - if (displayProperties != null && displayProperties.ContainsKey("Lore")) + if (NBT["display"] is Dictionary displayProperties && displayProperties.ContainsKey("Lore")) { - object[] displayName = displayProperties["Lore"] as object[]; - foreach (string st in displayName) - { - string str = MinecraftClient.Protocol.ChatParser.ParseText(st.ToString()); - lores.Add(str); - } + object[] displayName = (object[])displayProperties["Lore"]; + lores.AddRange(from string st in displayName + let str = MinecraftClient.Protocol.ChatParser.ParseText(st.ToString()) + select str); return lores.ToArray(); } } return null; } } - + /// /// Retrieve item damage from NBT properties. Returns 0 if no damage is defined. /// @@ -109,7 +105,7 @@ namespace MinecraftClient.Inventory object damage = NBT["Damage"]; if (damage != null) { - return int.Parse(damage.ToString()); + return int.Parse(damage.ToString() ?? string.Empty); } } return 0; @@ -118,18 +114,18 @@ namespace MinecraftClient.Inventory public override string ToString() { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new(); + sb.AppendFormat("x{0,-2} {1}", Count, Type.ToString()); - string displayName = DisplayName; + + string? displayName = DisplayName; if (!String.IsNullOrEmpty(displayName)) - { sb.AppendFormat(" - {0}§8", displayName); - } + int damage = Damage; if (damage != 0) - { sb.AppendFormat(" | {0}: {1}", Translations.Get("cmd.inventory.damage"), damage); - } + return sb.ToString(); } } diff --git a/MinecraftClient/Inventory/ItemMovingHelper.cs b/MinecraftClient/Inventory/ItemMovingHelper.cs index 08c9d5bd..07b1e686 100644 --- a/MinecraftClient/Inventory/ItemMovingHelper.cs +++ b/MinecraftClient/Inventory/ItemMovingHelper.cs @@ -1,8 +1,5 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; namespace MinecraftClient.Inventory { @@ -11,8 +8,8 @@ namespace MinecraftClient.Inventory /// public class ItemMovingHelper { - private Container c; - private McClient mc; + private readonly Container c; + private readonly McClient mc; /// /// Create a helper that contains useful methods to move item around in container @@ -35,7 +32,7 @@ namespace MinecraftClient.Inventory /// Dest slot /// Dest slot's container (only if dest slot is in other container) /// True if success or false if Failed - public bool MoveTo(int source, int dest, Container destContainer = null) + public bool MoveTo(int source, int dest, Container? destContainer = null) { // Condition: source has item and dest has no item if (ValidateSlots(source, dest, destContainer) && @@ -53,7 +50,7 @@ namespace MinecraftClient.Inventory /// Slot 2 /// Slot2 container (only if slot2 is in other container) /// True if success or False if Failed - public bool Swap(int slot1, int slot2, Container destContainer = null) + public bool Swap(int slot1, int slot2, Container? destContainer = null) { // Condition: Both slot1 and slot2 has item if (ValidateSlots(slot1, slot2, destContainer) && @@ -79,7 +76,7 @@ namespace MinecraftClient.Inventory { if (!HasItem(source)) return false; - List availableSlots = new List(slots.Count()); + List availableSlots = new(slots.Count()); // filter out different item type or non-empty slots (they will be ignored silently) foreach (var slot in slots) if (ItemTypeEqual(source, slot) || !HasItem(slot)) @@ -126,7 +123,7 @@ namespace MinecraftClient.Inventory /// Slot 2 /// Second container (only if slot2 is in other container) /// The compare result - private bool ValidateSlots(int s1, int s2, Container s2Container = null) + private bool ValidateSlots(int s1, int s2, Container? s2Container = null) { if (s2Container == null) return (s1 != s2 && s1 < c.Type.SlotCount() && s2 < c.Type.SlotCount()); @@ -140,10 +137,9 @@ namespace MinecraftClient.Inventory /// Slot ID /// Specify another contianer (only if the slot is in other container) /// True if has item - private bool HasItem(int slot, Container c = null) + private bool HasItem(int slot, Container? c = null) { - if (c == null) - c = this.c; + c ??= this.c; return c.Items.ContainsKey(slot); } @@ -154,7 +150,7 @@ namespace MinecraftClient.Inventory /// /// Second container (only if slot2 is in other container) /// True if they are equal - private bool ItemTypeEqual(int slot1, int slot2, Container s2Container = null) + private bool ItemTypeEqual(int slot1, int slot2, Container? s2Container = null) { if (s2Container == null) { diff --git a/MinecraftClient/Inventory/ItemPalettes/ItemPalette.cs b/MinecraftClient/Inventory/ItemPalettes/ItemPalette.cs index 74de67b8..84f04bfa 100644 --- a/MinecraftClient/Inventory/ItemPalettes/ItemPalette.cs +++ b/MinecraftClient/Inventory/ItemPalettes/ItemPalette.cs @@ -1,14 +1,11 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace MinecraftClient.Inventory.ItemPalettes { public abstract class ItemPalette { protected abstract Dictionary GetDict(); - private readonly Dictionary DictReverse = new Dictionary(); + private readonly Dictionary DictReverse = new(); public ItemPalette() { diff --git a/MinecraftClient/Inventory/ItemPalettes/ItemPalette115.cs b/MinecraftClient/Inventory/ItemPalettes/ItemPalette115.cs index d69e143f..0ca43415 100644 --- a/MinecraftClient/Inventory/ItemPalettes/ItemPalette115.cs +++ b/MinecraftClient/Inventory/ItemPalettes/ItemPalette115.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Inventory.ItemPalettes @@ -9,7 +8,7 @@ namespace MinecraftClient.Inventory.ItemPalettes /// public class ItemPalette115 : ItemPalette { - private static Dictionary mappings = new Dictionary(); + private static readonly Dictionary mappings = new(); static ItemPalette115() { diff --git a/MinecraftClient/Inventory/ItemPalettes/ItemPalette1161.cs b/MinecraftClient/Inventory/ItemPalettes/ItemPalette1161.cs index 0b0504c2..a953ec2a 100644 --- a/MinecraftClient/Inventory/ItemPalettes/ItemPalette1161.cs +++ b/MinecraftClient/Inventory/ItemPalettes/ItemPalette1161.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Inventory.ItemPalettes @@ -9,7 +8,7 @@ namespace MinecraftClient.Inventory.ItemPalettes /// public class ItemPalette1161 : ItemPalette { - private static Dictionary mappings = new Dictionary(); + private static readonly Dictionary mappings = new(); static ItemPalette1161() { diff --git a/MinecraftClient/Inventory/ItemPalettes/ItemPalette1162.cs b/MinecraftClient/Inventory/ItemPalettes/ItemPalette1162.cs index aa674f45..b2094614 100644 --- a/MinecraftClient/Inventory/ItemPalettes/ItemPalette1162.cs +++ b/MinecraftClient/Inventory/ItemPalettes/ItemPalette1162.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Inventory.ItemPalettes @@ -9,7 +8,7 @@ namespace MinecraftClient.Inventory.ItemPalettes /// public class ItemPalette1162 : ItemPalette { - private static Dictionary mappings = new Dictionary(); + private static readonly Dictionary mappings = new(); static ItemPalette1162() { diff --git a/MinecraftClient/Inventory/ItemPalettes/ItemPalette117.cs b/MinecraftClient/Inventory/ItemPalettes/ItemPalette117.cs index 35d903ab..92715541 100644 --- a/MinecraftClient/Inventory/ItemPalettes/ItemPalette117.cs +++ b/MinecraftClient/Inventory/ItemPalettes/ItemPalette117.cs @@ -1,11 +1,10 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Inventory.ItemPalettes { public class ItemPalette117 : ItemPalette { - private static Dictionary mappings = new Dictionary(); + private static readonly Dictionary mappings = new(); static ItemPalette117() { diff --git a/MinecraftClient/Inventory/ItemPalettes/ItemPalette118.cs b/MinecraftClient/Inventory/ItemPalettes/ItemPalette118.cs index d8e1d61d..a37a61a6 100644 --- a/MinecraftClient/Inventory/ItemPalettes/ItemPalette118.cs +++ b/MinecraftClient/Inventory/ItemPalettes/ItemPalette118.cs @@ -1,11 +1,10 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Inventory.ItemPalettes { public class ItemPalette118 : ItemPalette { - private static Dictionary mappings = new Dictionary(); + private static readonly Dictionary mappings = new(); static ItemPalette118() { diff --git a/MinecraftClient/Inventory/ItemPalettes/ItemPalette119.cs b/MinecraftClient/Inventory/ItemPalettes/ItemPalette119.cs index c0540f4a..48a9a6ea 100644 --- a/MinecraftClient/Inventory/ItemPalettes/ItemPalette119.cs +++ b/MinecraftClient/Inventory/ItemPalettes/ItemPalette119.cs @@ -1,11 +1,10 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Inventory.ItemPalettes { public class ItemPalette119 : ItemPalette { - private static Dictionary mappings = new Dictionary(); + private static readonly Dictionary mappings = new(); static ItemPalette119() { diff --git a/MinecraftClient/Inventory/ItemPalettes/ItemPaletteGenerator.cs b/MinecraftClient/Inventory/ItemPalettes/ItemPaletteGenerator.cs index c58dd57e..eed9b844 100644 --- a/MinecraftClient/Inventory/ItemPalettes/ItemPaletteGenerator.cs +++ b/MinecraftClient/Inventory/ItemPalettes/ItemPaletteGenerator.cs @@ -1,8 +1,4 @@ using MinecraftClient.Protocol; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient.Inventory.ItemPalettes { @@ -18,8 +14,8 @@ namespace MinecraftClient.Inventory.ItemPalettes { DataTypeGenerator.GenerateEnumWithPalette( registriesJsonFile, - "minecraft:item", - "ItemType", + "minecraft:item", + "ItemType", "MinecraftClient.Inventory", "ItemPalette", "MinecraftClient.Inventory.ItemPalettes"); diff --git a/MinecraftClient/Inventory/ItemTypeExtensions.cs b/MinecraftClient/Inventory/ItemTypeExtensions.cs index 5c1c8ac4..7f3e5f75 100644 --- a/MinecraftClient/Inventory/ItemTypeExtensions.cs +++ b/MinecraftClient/Inventory/ItemTypeExtensions.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; namespace MinecraftClient.Inventory { diff --git a/MinecraftClient/Inventory/VillagerTrade.cs b/MinecraftClient/Inventory/VillagerTrade.cs index 4e1948b4..70246cab 100644 --- a/MinecraftClient/Inventory/VillagerTrade.cs +++ b/MinecraftClient/Inventory/VillagerTrade.cs @@ -7,7 +7,7 @@ { public Item InputItem1; public Item OutputItem; - public Item InputItem2; + public Item? InputItem2; public bool TradeDisabled; public int NumberOfTradeUses; public int MaximumNumberOfTradeUses; @@ -16,18 +16,18 @@ public float PriceMultiplier; public int Demand; - public VillagerTrade(Item inputItem1, Item outputItem, Item inputItem2, bool tradeDisabled, int numberOfTradeUses, int maximumNumberOfTradeUses, int xp, int specialPrice, float priceMultiplier, int demand) + public VillagerTrade(Item inputItem1, Item outputItem, Item? inputItem2, bool tradeDisabled, int numberOfTradeUses, int maximumNumberOfTradeUses, int xp, int specialPrice, float priceMultiplier, int demand) { - this.InputItem1 = inputItem1; - this.OutputItem = outputItem; - this.InputItem2 = inputItem2; - this.TradeDisabled = tradeDisabled; - this.NumberOfTradeUses = numberOfTradeUses; - this.MaximumNumberOfTradeUses = maximumNumberOfTradeUses; - this.Xp = xp; - this.SpecialPrice = specialPrice; - this.PriceMultiplier = priceMultiplier; - this.Demand = demand; + InputItem1 = inputItem1; + OutputItem = outputItem; + InputItem2 = inputItem2; + TradeDisabled = tradeDisabled; + NumberOfTradeUses = numberOfTradeUses; + MaximumNumberOfTradeUses = maximumNumberOfTradeUses; + Xp = xp; + SpecialPrice = specialPrice; + PriceMultiplier = priceMultiplier; + Demand = demand; } } } diff --git a/MinecraftClient/Inventory/WindowActionType.cs b/MinecraftClient/Inventory/WindowActionType.cs index f25aea84..a0b9d904 100644 --- a/MinecraftClient/Inventory/WindowActionType.cs +++ b/MinecraftClient/Inventory/WindowActionType.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MinecraftClient.Inventory +namespace MinecraftClient.Inventory { /// /// Represents mouse interactions with an inventory window diff --git a/MinecraftClient/Json.cs b/MinecraftClient/Json.cs index 1904f494..06722166 100644 --- a/MinecraftClient/Json.cs +++ b/MinecraftClient/Json.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; namespace MinecraftClient @@ -27,7 +26,7 @@ namespace MinecraftClient public class JSONData { public enum DataType { Object, Array, String }; - private DataType type; + private readonly DataType type; public DataType Type { get { return type; } } public Dictionary Properties; public List DataArray; @@ -137,9 +136,20 @@ namespace MinecraftClient break; //Number - case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '.': + case '-': data = new JSONData(JSONData.DataType.String); - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new(); while ((toparse[cursorpos] >= '0' && toparse[cursorpos] <= '9') || toparse[cursorpos] == '.' || toparse[cursorpos] == '-') { sb.Append(toparse[cursorpos]); diff --git a/MinecraftClient/Logger/FileLogLogger.cs b/MinecraftClient/Logger/FileLogLogger.cs index 6dab993f..f065ed83 100644 --- a/MinecraftClient/Logger/FileLogLogger.cs +++ b/MinecraftClient/Logger/FileLogLogger.cs @@ -1,16 +1,13 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.IO; namespace MinecraftClient.Logger { public class FileLogLogger : FilteredLogger { - private string logFile; - private bool prependTimestamp; - private object logFileLock = new object(); + private readonly string logFile; + private readonly bool prependTimestamp; + private readonly object logFileLock = new(); public FileLogLogger(string file, bool prependTimestamp = false) { @@ -34,13 +31,13 @@ namespace MinecraftClient.Logger if (prependTimestamp) msg = GetTimestamp() + ' ' + msg; - string directory = Path.GetDirectoryName(logFile); + string? directory = Path.GetDirectoryName(logFile); if (!String.IsNullOrEmpty(directory) && !Directory.Exists(directory)) Directory.CreateDirectory(directory); lock (logFileLock) { - FileStream stream = new FileStream(logFile, FileMode.OpenOrCreate); - StreamWriter writer = new StreamWriter(stream); + FileStream stream = new(logFile, FileMode.OpenOrCreate); + StreamWriter writer = new(stream); stream.Seek(0, SeekOrigin.End); writer.WriteLine(msg); writer.Dispose(); diff --git a/MinecraftClient/Logger/FilteredLogger.cs b/MinecraftClient/Logger/FilteredLogger.cs index 288d75f2..d3878f89 100644 --- a/MinecraftClient/Logger/FilteredLogger.cs +++ b/MinecraftClient/Logger/FilteredLogger.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; +using System.Text.RegularExpressions; namespace MinecraftClient.Logger { @@ -12,9 +8,9 @@ namespace MinecraftClient.Logger protected bool ShouldDisplay(FilterChannel channel, string msg) { - Regex regexToUse = null; + Regex? regexToUse = null; // Convert to bool for XOR later. Whitelist = 0, Blacklist = 1 - bool filterMode = Settings.FilterMode == Settings.FilterModeEnum.Blacklist ? true : false; + bool filterMode = Settings.FilterMode == Settings.FilterModeEnum.Blacklist; switch (channel) { case FilterChannel.Chat: regexToUse = Settings.ChatFilter; break; diff --git a/MinecraftClient/Logger/ILogger.cs b/MinecraftClient/Logger/ILogger.cs index 98b810d2..ba3f143f 100644 --- a/MinecraftClient/Logger/ILogger.cs +++ b/MinecraftClient/Logger/ILogger.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MinecraftClient.Logger +namespace MinecraftClient.Logger { public interface ILogger { diff --git a/MinecraftClient/Logger/LoggerBase.cs b/MinecraftClient/Logger/LoggerBase.cs index 1ea31c6d..8569bfc9 100644 --- a/MinecraftClient/Logger/LoggerBase.cs +++ b/MinecraftClient/Logger/LoggerBase.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MinecraftClient.Logger +namespace MinecraftClient.Logger { /// /// Abstract class providing basic implementation of the ILogger interface @@ -30,7 +25,7 @@ namespace MinecraftClient.Logger public void Chat(object msg) { - Chat(msg.ToString()); + Chat(msg.ToString() ?? string.Empty); } public abstract void Debug(string msg); @@ -42,7 +37,7 @@ namespace MinecraftClient.Logger public void Debug(object msg) { - Debug(msg.ToString()); + Debug(msg.ToString() ?? string.Empty); } public abstract void Error(string msg); @@ -54,7 +49,7 @@ namespace MinecraftClient.Logger public void Error(object msg) { - Error(msg.ToString()); + Error(msg.ToString() ?? string.Empty); } public abstract void Info(string msg); @@ -66,7 +61,7 @@ namespace MinecraftClient.Logger public void Info(object msg) { - Info(msg.ToString()); + Info(msg.ToString() ?? string.Empty); } public abstract void Warn(string msg); @@ -78,12 +73,12 @@ namespace MinecraftClient.Logger public void Warn(object msg) { - Warn(msg.ToString()); + Warn(msg.ToString() ?? string.Empty); } protected virtual void Log(object msg) { - ConsoleIO.WriteLineFormatted(msg.ToString()); + ConsoleIO.WriteLineFormatted(msg.ToString() ?? string.Empty); } protected virtual void Log(string msg) diff --git a/MinecraftClient/Mapping/Block.cs b/MinecraftClient/Mapping/Block.cs index 5aa1f382..595356ab 100644 --- a/MinecraftClient/Mapping/Block.cs +++ b/MinecraftClient/Mapping/Block.cs @@ -1,8 +1,5 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Runtime.CompilerServices; -using System.Text; using MinecraftClient.Mapping.BlockPalettes; namespace MinecraftClient.Mapping @@ -18,7 +15,7 @@ namespace MinecraftClient.Mapping /// Get or set global block ID to Material mapping /// The global Palette is a concept introduced with Minecraft 1.13 /// - public static BlockPalette Palette { get; set; } + public static BlockPalette Palette { get; set; } = new Palette112(); /// /// Storage for block ID and metadata, as ushort for compatibility, performance and lower memory footprint @@ -45,13 +42,13 @@ namespace MinecraftClient.Mapping if (Palette.IdHasMetadata) { if (value > (ushort.MaxValue >> 4) || value < 0) - throw new ArgumentOutOfRangeException("value", "Invalid block ID. Accepted range: 0-4095"); + throw new ArgumentOutOfRangeException(nameof(value), "Invalid block ID. Accepted range: 0-4095"); blockIdAndMeta = (ushort)(value << 4 | BlockMeta); } else { if (value > ushort.MaxValue || value < 0) - throw new ArgumentOutOfRangeException("value", "Invalid block ID. Accepted range: 0-65535"); + throw new ArgumentOutOfRangeException(nameof(value), "Invalid block ID. Accepted range: 0-65535"); blockIdAndMeta = (ushort)value; } } @@ -100,9 +97,9 @@ namespace MinecraftClient.Mapping { if (!Palette.IdHasMetadata) throw new InvalidOperationException("Current global Palette does not support block Metadata"); - this.blockIdAndMeta = 0; - this.BlockId = type; - this.BlockMeta = metadata; + blockIdAndMeta = 0; + BlockId = type; + BlockMeta = metadata; } /// @@ -112,7 +109,7 @@ namespace MinecraftClient.Mapping [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public Block(ushort typeAndMeta) { - this.blockIdAndMeta = typeAndMeta; + blockIdAndMeta = typeAndMeta; } /// diff --git a/MinecraftClient/Mapping/BlockPalettes/BlockPalette.cs b/MinecraftClient/Mapping/BlockPalettes/BlockPalette.cs index 9b8611b6..a3cd7986 100644 --- a/MinecraftClient/Mapping/BlockPalettes/BlockPalette.cs +++ b/MinecraftClient/Mapping/BlockPalettes/BlockPalette.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace MinecraftClient.Mapping.BlockPalettes { diff --git a/MinecraftClient/Mapping/BlockPalettes/BlockPaletteGenerator.cs b/MinecraftClient/Mapping/BlockPalettes/BlockPaletteGenerator.cs index 831b3abe..57675b5f 100644 --- a/MinecraftClient/Mapping/BlockPalettes/BlockPaletteGenerator.cs +++ b/MinecraftClient/Mapping/BlockPalettes/BlockPaletteGenerator.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; using System.IO; +using System.Linq; using System.Text; namespace MinecraftClient.Mapping.BlockPalettes @@ -42,13 +42,13 @@ namespace MinecraftClient.Mapping.BlockPalettes /// output path for material.cs /// java -cp minecraft_server.jar net.minecraft.data.Main --reports /// state => block name mappings - public static void JsonToClass(string blocksJsonFile, string outputClass, string outputEnum = null) + public static void JsonToClass(string blocksJsonFile, string outputClass, string? outputEnum = null) { - string outputPalettePath = Path.Combine(Path.GetDirectoryName(blocksJsonFile), outputClass + "XXX.cs"); - string outputEnumPath = Path.Combine(Path.GetDirectoryName(blocksJsonFile), outputEnum + "XXX.cs"); + string outputPalettePath = Path.Combine(Path.GetDirectoryName(blocksJsonFile)!, outputClass + "XXX.cs"); + string outputEnumPath = Path.Combine(Path.GetDirectoryName(blocksJsonFile)!, outputEnum + "XXX.cs"); - HashSet knownStates = new HashSet(); - Dictionary> blocks = new Dictionary>(); + HashSet knownStates = new(); + Dictionary> blocks = new(); Json.JSONData palette = Json.ParseJson(File.ReadAllText(blocksJsonFile, Encoding.UTF8)); foreach (KeyValuePair item in palette.Properties) @@ -76,17 +76,16 @@ namespace MinecraftClient.Mapping.BlockPalettes } } - HashSet materials = new HashSet(); - List outFile = new List(); + HashSet materials = new(); + List outFile = new(); outFile.AddRange(new[] { - "using System;", "using System.Collections.Generic;", "", "namespace MinecraftClient.Mapping.BlockPalettes", "{", " public class PaletteXXX : BlockPalette", " {", - " private static Dictionary materials = new Dictionary();", + " private static readonly Dictionary materials = new();", "", " static PaletteXXX()", " {", @@ -103,7 +102,7 @@ namespace MinecraftClient.Mapping.BlockPalettes if (idList.Count > 1) { idList.Sort(); - Queue idQueue = new Queue(idList); + Queue idQueue = new(idList); while (idQueue.Count > 0) { diff --git a/MinecraftClient/Mapping/BlockPalettes/Palette112.cs b/MinecraftClient/Mapping/BlockPalettes/Palette112.cs index 7afc42ad..02dde423 100644 --- a/MinecraftClient/Mapping/BlockPalettes/Palette112.cs +++ b/MinecraftClient/Mapping/BlockPalettes/Palette112.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Mapping.BlockPalettes @@ -11,7 +10,7 @@ namespace MinecraftClient.Mapping.BlockPalettes /// public class Palette112 : BlockPalette { - private static Dictionary materials = new Dictionary() + private static readonly Dictionary materials = new() { { 0, Material.Air }, { 1, Material.Stone }, diff --git a/MinecraftClient/Mapping/BlockPalettes/Palette113.cs b/MinecraftClient/Mapping/BlockPalettes/Palette113.cs index b0e2006d..55be9672 100644 --- a/MinecraftClient/Mapping/BlockPalettes/Palette113.cs +++ b/MinecraftClient/Mapping/BlockPalettes/Palette113.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Mapping.BlockPalettes @@ -9,7 +8,7 @@ namespace MinecraftClient.Mapping.BlockPalettes /// public class Palette113 : BlockPalette { - private static Dictionary materials = new Dictionary(); + private static readonly Dictionary materials = new(); static Palette113() { diff --git a/MinecraftClient/Mapping/BlockPalettes/Palette114.cs b/MinecraftClient/Mapping/BlockPalettes/Palette114.cs index b44b20d6..b21e0830 100644 --- a/MinecraftClient/Mapping/BlockPalettes/Palette114.cs +++ b/MinecraftClient/Mapping/BlockPalettes/Palette114.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Mapping.BlockPalettes @@ -9,7 +8,7 @@ namespace MinecraftClient.Mapping.BlockPalettes /// public class Palette114 : BlockPalette { - private static Dictionary materials = new Dictionary(); + private static readonly Dictionary materials = new(); static Palette114() { diff --git a/MinecraftClient/Mapping/BlockPalettes/Palette115.cs b/MinecraftClient/Mapping/BlockPalettes/Palette115.cs index e84fbd11..b43a1ce9 100644 --- a/MinecraftClient/Mapping/BlockPalettes/Palette115.cs +++ b/MinecraftClient/Mapping/BlockPalettes/Palette115.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Mapping.BlockPalettes @@ -9,7 +8,7 @@ namespace MinecraftClient.Mapping.BlockPalettes /// public class Palette115 : BlockPalette { - private static Dictionary materials = new Dictionary(); + private static readonly Dictionary materials = new(); static Palette115() { diff --git a/MinecraftClient/Mapping/BlockPalettes/Palette116.cs b/MinecraftClient/Mapping/BlockPalettes/Palette116.cs index 1d63b6b4..3b2524f5 100644 --- a/MinecraftClient/Mapping/BlockPalettes/Palette116.cs +++ b/MinecraftClient/Mapping/BlockPalettes/Palette116.cs @@ -1,11 +1,10 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Mapping.BlockPalettes { public class Palette116 : BlockPalette { - private static Dictionary materials = new Dictionary(); + private static readonly Dictionary materials = new(); static Palette116() { diff --git a/MinecraftClient/Mapping/BlockPalettes/Palette117.cs b/MinecraftClient/Mapping/BlockPalettes/Palette117.cs index 826b630e..ff0358d1 100644 --- a/MinecraftClient/Mapping/BlockPalettes/Palette117.cs +++ b/MinecraftClient/Mapping/BlockPalettes/Palette117.cs @@ -1,11 +1,10 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Mapping.BlockPalettes { public class Palette117 : BlockPalette { - private static Dictionary materials = new Dictionary(); + private static readonly Dictionary materials = new(); static Palette117() { diff --git a/MinecraftClient/Mapping/BlockPalettes/Palette119.cs b/MinecraftClient/Mapping/BlockPalettes/Palette119.cs index 88521065..ab276fee 100644 --- a/MinecraftClient/Mapping/BlockPalettes/Palette119.cs +++ b/MinecraftClient/Mapping/BlockPalettes/Palette119.cs @@ -1,11 +1,10 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Mapping.BlockPalettes { public class Palette119 : BlockPalette { - private static Dictionary materials = new Dictionary(); + private static readonly Dictionary materials = new(); static Palette119() { diff --git a/MinecraftClient/Mapping/Chunk.cs b/MinecraftClient/Mapping/Chunk.cs index 90ef604e..4041343b 100644 --- a/MinecraftClient/Mapping/Chunk.cs +++ b/MinecraftClient/Mapping/Chunk.cs @@ -1,9 +1,5 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Runtime.CompilerServices; -using System.Text; -using System.Threading; namespace MinecraftClient.Mapping { diff --git a/MinecraftClient/Mapping/ChunkColumn.cs b/MinecraftClient/Mapping/ChunkColumn.cs index 5e40c954..38f37c63 100644 --- a/MinecraftClient/Mapping/ChunkColumn.cs +++ b/MinecraftClient/Mapping/ChunkColumn.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; namespace MinecraftClient.Mapping { diff --git a/MinecraftClient/Mapping/CommandBlockFlags.cs b/MinecraftClient/Mapping/CommandBlockFlags.cs index 5807222e..9241fa61 100644 --- a/MinecraftClient/Mapping/CommandBlockFlags.cs +++ b/MinecraftClient/Mapping/CommandBlockFlags.cs @@ -1,8 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - namespace MinecraftClient.Mapping { /// diff --git a/MinecraftClient/Mapping/CommandBlockMode.cs b/MinecraftClient/Mapping/CommandBlockMode.cs index 6d4aba67..9dd492ce 100644 --- a/MinecraftClient/Mapping/CommandBlockMode.cs +++ b/MinecraftClient/Mapping/CommandBlockMode.cs @@ -1,8 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - namespace MinecraftClient.Mapping { /// diff --git a/MinecraftClient/Mapping/Dimension.cs b/MinecraftClient/Mapping/Dimension.cs index d260ce71..3aea6744 100644 --- a/MinecraftClient/Mapping/Dimension.cs +++ b/MinecraftClient/Mapping/Dimension.cs @@ -1,8 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace MinecraftClient.Mapping { @@ -120,7 +117,7 @@ namespace MinecraftClient.Mapping /// public Dimension() { - this.Name = "minecraft:overworld"; + Name = "minecraft:overworld"; } /// @@ -130,73 +127,66 @@ namespace MinecraftClient.Mapping /// The dimension type (NBT Tag Compound) public Dimension(string name, Dictionary nbt) { - if (name == null) - throw new ArgumentNullException("name"); - if (nbt == null) - throw new ArgumentNullException("nbt Data"); + Name = name ?? throw new ArgumentNullException(nameof(name)); - this.Name = name; + if (nbt == null) + throw new ArgumentNullException(nameof(nbt)); if (nbt.ContainsKey("piglin_safe")) - this.piglinSafe = 1 == (byte)nbt["piglin_safe"]; + piglinSafe = Convert.ToBoolean(nbt["piglin_safe"]); if (nbt.ContainsKey("monster_spawn_light_level")) { try { var monsterSpawnLightLevelObj = nbt["monster_spawn_light_level"]; - if (monsterSpawnLightLevelObj.GetType() == typeof(int)) - this.monsterSpawnMinLightLevel = this.monsterSpawnMaxLightLevel = (int)monsterSpawnLightLevelObj; - else + try + { + monsterSpawnMinLightLevel = monsterSpawnMaxLightLevel = Convert.ToInt32(monsterSpawnLightLevelObj); + } + catch (Exception) { var inclusive = (Dictionary)(((Dictionary)monsterSpawnLightLevelObj)["value"]); - this.monsterSpawnMinLightLevel = (int)inclusive["min_inclusive"]; - this.monsterSpawnMaxLightLevel = (int)inclusive["max_inclusive"]; + monsterSpawnMinLightLevel = Convert.ToInt32(inclusive["min_inclusive"]); + monsterSpawnMaxLightLevel = Convert.ToInt32(inclusive["max_inclusive"]); } } catch (KeyNotFoundException) { } } if (nbt.ContainsKey("monster_spawn_block_light_limit")) - this.monsterSpawnBlockLightLimit = (int)nbt["monster_spawn_block_light_limit"]; + monsterSpawnBlockLightLimit = Convert.ToInt32(nbt["monster_spawn_block_light_limit"]); if (nbt.ContainsKey("natural")) - this.natural = 1 == (byte)nbt["natural"]; + natural = Convert.ToBoolean(nbt["natural"]); if (nbt.ContainsKey("ambient_light")) - this.ambientLight = (float)nbt["ambient_light"]; + ambientLight = (float)Convert.ToDouble(nbt["ambient_light"]); if (nbt.ContainsKey("fixed_time")) - this.fixedTime = (long)nbt["fixed_time"]; + fixedTime = Convert.ToInt64(nbt["fixed_time"]); if (nbt.ContainsKey("infiniburn")) - this.infiniburn = (string)nbt["infiniburn"]; + infiniburn = Convert.ToString(nbt["infiniburn"]) ?? string.Empty; if (nbt.ContainsKey("respawn_anchor_works")) - this.respawnAnchorWorks = 1 == (byte)nbt["respawn_anchor_works"]; + respawnAnchorWorks = Convert.ToBoolean(nbt["respawn_anchor_works"]); if (nbt.ContainsKey("has_skylight")) - this.hasSkylight = 1 == (byte)nbt["has_skylight"]; + hasSkylight = Convert.ToBoolean(nbt["has_skylight"]); if (nbt.ContainsKey("bed_works")) - this.bedWorks = 1 == (byte)nbt["bed_works"]; + bedWorks = Convert.ToBoolean(nbt["bed_works"]); if (nbt.ContainsKey("effects")) - this.effects = (string)nbt["effects"]; + effects = Convert.ToString(nbt["effects"]) ?? string.Empty; if (nbt.ContainsKey("has_raids")) - this.hasRaids = 1 == (byte)nbt["has_raids"]; + hasRaids = Convert.ToBoolean(nbt["has_raids"]); if (nbt.ContainsKey("min_y")) - this.minY = (int)nbt["min_y"]; + minY = Convert.ToInt32(nbt["min_y"]); if (nbt.ContainsKey("height")) - this.height = (int)nbt["height"]; + height = Convert.ToInt32(nbt["height"]); if (nbt.ContainsKey("min_y") && nbt.ContainsKey("height")) - this.maxY = this.minY + this.height; + maxY = minY + height; if (nbt.ContainsKey("logical_height") && nbt["logical_height"].GetType() != typeof(byte)) - this.logicalHeight = (int)nbt["logical_height"]; + logicalHeight = Convert.ToInt32(nbt["logical_height"]); if (nbt.ContainsKey("coordinate_scale")) - { - var coordinateScaleObj = nbt["coordinate_scale"]; - if (coordinateScaleObj.GetType() == typeof(float)) - this.coordinateScale = (float)coordinateScaleObj; - else - this.coordinateScale = (double)coordinateScaleObj; - } + coordinateScale = Convert.ToDouble(nbt["coordinate_scale"]); if (nbt.ContainsKey("ultrawarm")) - this.ultrawarm = 1 == (byte)nbt["ultrawarm"]; + ultrawarm = Convert.ToBoolean(nbt["ultrawarm"]); if (nbt.ContainsKey("has_ceiling")) - this.hasCeiling = 1 == (byte)nbt["has_ceiling"]; + hasCeiling = Convert.ToBoolean(nbt["has_ceiling"]); } - } } diff --git a/MinecraftClient/Mapping/Direction.cs b/MinecraftClient/Mapping/Direction.cs index 209d97e2..9f3ed7fe 100644 --- a/MinecraftClient/Mapping/Direction.cs +++ b/MinecraftClient/Mapping/Direction.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MinecraftClient.Mapping +namespace MinecraftClient.Mapping { /// /// Represents a unit movement in the world diff --git a/MinecraftClient/Mapping/Entity.cs b/MinecraftClient/Mapping/Entity.cs index e32f43e8..bd19247b 100644 --- a/MinecraftClient/Mapping/Entity.cs +++ b/MinecraftClient/Mapping/Entity.cs @@ -23,12 +23,12 @@ namespace MinecraftClient.Mapping /// Nickname of the entity if it is a player. /// public string? Name; - + /// /// CustomName of the entity. /// - public string CustomNameJson; - + public string? CustomNameJson; + /// /// IsCustomNameVisible of the entity. /// @@ -37,8 +37,8 @@ namespace MinecraftClient.Mapping /// /// CustomName of the entity. /// - public string CustomName; - + public string? CustomName; + /// /// Latency of the entity if it is a player. /// @@ -77,21 +77,21 @@ namespace MinecraftClient.Mapping /// Health of the entity /// public float Health; - + /// /// Item of the entity if ItemFrame or Item /// public Item Item; - + /// /// Entity pose in the Minecraft world /// public EntityPose Pose; - + /// /// Entity metadata /// - public Dictionary Metadata; + public Dictionary? Metadata; /// /// Entity equipment @@ -107,11 +107,11 @@ namespace MinecraftClient.Mapping public Entity(int ID, EntityType type, Location location) { this.ID = ID; - this.Type = type; - this.Location = location; - this.Health = 1.0f; - this.Equipment = new Dictionary(); - this.Item = new Item(ItemType.Air, 0, null); + Type = type; + Location = location; + Health = 1.0f; + Equipment = new Dictionary(); + Item = new Item(ItemType.Air, 0, null); } /// @@ -123,14 +123,14 @@ namespace MinecraftClient.Mapping public Entity(int ID, EntityType type, Location location, byte yaw, byte pitch, int objectData) { this.ID = ID; - this.Type = type; - this.Location = location; - this.Health = 1.0f; - this.Equipment = new Dictionary(); - this.Item = new Item(ItemType.Air, 0, null); - this.Yaw = yaw * (1 / 256) * 360; // to angle in 360 degree - this.Pitch = pitch * (1 / 256) * 360; - this.ObjectData = objectData; + Type = type; + Location = location; + Health = 1.0f; + Equipment = new Dictionary(); + Item = new Item(ItemType.Air, 0, null); + Yaw = yaw * (1 / 256) * 360; // to angle in 360 degree + Pitch = pitch * (1 / 256) * 360; + ObjectData = objectData; } /// @@ -144,15 +144,15 @@ namespace MinecraftClient.Mapping public Entity(int ID, EntityType type, Location location, Guid uuid, string? name, byte yaw, byte pitch) { this.ID = ID; - this.Type = type; - this.Location = location; - this.UUID = uuid; - this.Name = name; - this.Health = 1.0f; - this.Equipment = new Dictionary(); - this.Item = new Item(ItemType.Air, 0, null); - this.Yaw = yaw * (1 / 256) * 360; // to angle in 360 degree - this.Pitch = pitch * (1 / 256) * 360; + Type = type; + Location = location; + UUID = uuid; + Name = name; + Health = 1.0f; + Equipment = new Dictionary(); + Item = new Item(ItemType.Air, 0, null); + Yaw = yaw * (1 / 256) * 360; // to angle in 360 degree + Pitch = pitch * (1 / 256) * 360; } } } diff --git a/MinecraftClient/Mapping/EntityPalettes/EntityPalette.cs b/MinecraftClient/Mapping/EntityPalettes/EntityPalette.cs index df7abd5d..d1e30c16 100644 --- a/MinecraftClient/Mapping/EntityPalettes/EntityPalette.cs +++ b/MinecraftClient/Mapping/EntityPalettes/EntityPalette.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace MinecraftClient.Mapping.EntityPalettes { @@ -17,7 +14,7 @@ namespace MinecraftClient.Mapping.EntityPalettes /// Get mapping dictionary for pre-1.14 non-living entities. /// /// Palette dictionary for non-living entities (pre-1.14) - protected virtual Dictionary GetDictNonLiving() + protected virtual Dictionary? GetDictNonLiving() { return null; } @@ -30,7 +27,7 @@ namespace MinecraftClient.Mapping.EntityPalettes public EntityType FromId(int id, bool living) { Dictionary entityTypes = GetDict(); - Dictionary entityTypesNonLiving = GetDictNonLiving(); + Dictionary? entityTypesNonLiving = GetDictNonLiving(); if (entityTypesNonLiving != null && !living) { diff --git a/MinecraftClient/Mapping/EntityPalettes/EntityPalette112.cs b/MinecraftClient/Mapping/EntityPalettes/EntityPalette112.cs index 322dff54..15d0dcd4 100644 --- a/MinecraftClient/Mapping/EntityPalettes/EntityPalette112.cs +++ b/MinecraftClient/Mapping/EntityPalettes/EntityPalette112.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; namespace MinecraftClient.Mapping.EntityPalettes { diff --git a/MinecraftClient/Mapping/EntityPalettes/EntityPalette113.cs b/MinecraftClient/Mapping/EntityPalettes/EntityPalette113.cs index 5d66bf37..cc1b1654 100644 --- a/MinecraftClient/Mapping/EntityPalettes/EntityPalette113.cs +++ b/MinecraftClient/Mapping/EntityPalettes/EntityPalette113.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Mapping.EntityPalettes diff --git a/MinecraftClient/Mapping/EntityPalettes/EntityPalette114.cs b/MinecraftClient/Mapping/EntityPalettes/EntityPalette114.cs index b0140581..a908cc1f 100644 --- a/MinecraftClient/Mapping/EntityPalettes/EntityPalette114.cs +++ b/MinecraftClient/Mapping/EntityPalettes/EntityPalette114.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Mapping.EntityPalettes @@ -9,7 +8,7 @@ namespace MinecraftClient.Mapping.EntityPalettes /// public class EntityPalette114 : EntityPalette { - private static Dictionary mappings = new Dictionary(); + private static readonly Dictionary mappings = new(); static EntityPalette114() { diff --git a/MinecraftClient/Mapping/EntityPalettes/EntityPalette115.cs b/MinecraftClient/Mapping/EntityPalettes/EntityPalette115.cs index 4d242f93..d8f67560 100644 --- a/MinecraftClient/Mapping/EntityPalettes/EntityPalette115.cs +++ b/MinecraftClient/Mapping/EntityPalettes/EntityPalette115.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Mapping.EntityPalettes @@ -9,7 +8,7 @@ namespace MinecraftClient.Mapping.EntityPalettes /// public class EntityPalette115 : EntityPalette { - private static Dictionary mappings = new Dictionary(); + private static readonly Dictionary mappings = new(); static EntityPalette115() { diff --git a/MinecraftClient/Mapping/EntityPalettes/EntityPalette1161.cs b/MinecraftClient/Mapping/EntityPalettes/EntityPalette1161.cs index 494fedd2..7aa83ea4 100644 --- a/MinecraftClient/Mapping/EntityPalettes/EntityPalette1161.cs +++ b/MinecraftClient/Mapping/EntityPalettes/EntityPalette1161.cs @@ -1,11 +1,10 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Mapping.EntityPalettes { public class EntityPalette1161 : EntityPalette { - private static Dictionary mappings = new Dictionary(); + private static readonly Dictionary mappings = new(); static EntityPalette1161() { diff --git a/MinecraftClient/Mapping/EntityPalettes/EntityPalette1162.cs b/MinecraftClient/Mapping/EntityPalettes/EntityPalette1162.cs index 6fc9be32..fcb00cd6 100644 --- a/MinecraftClient/Mapping/EntityPalettes/EntityPalette1162.cs +++ b/MinecraftClient/Mapping/EntityPalettes/EntityPalette1162.cs @@ -1,11 +1,10 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Mapping.EntityPalettes { public class EntityPalette1162 : EntityPalette { - private static Dictionary mappings = new Dictionary(); + private static readonly Dictionary mappings = new(); static EntityPalette1162() { diff --git a/MinecraftClient/Mapping/EntityPalettes/EntityPalette117.cs b/MinecraftClient/Mapping/EntityPalettes/EntityPalette117.cs index 65d9272a..ce292066 100644 --- a/MinecraftClient/Mapping/EntityPalettes/EntityPalette117.cs +++ b/MinecraftClient/Mapping/EntityPalettes/EntityPalette117.cs @@ -1,11 +1,10 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Mapping.EntityPalettes { public class EntityPalette117 : EntityPalette { - private static Dictionary mappings = new Dictionary(); + private static readonly Dictionary mappings = new(); static EntityPalette117() { diff --git a/MinecraftClient/Mapping/EntityPalettes/EntityPalette119.cs b/MinecraftClient/Mapping/EntityPalettes/EntityPalette119.cs index b85059cc..51f87e18 100644 --- a/MinecraftClient/Mapping/EntityPalettes/EntityPalette119.cs +++ b/MinecraftClient/Mapping/EntityPalettes/EntityPalette119.cs @@ -1,11 +1,10 @@ -using System; using System.Collections.Generic; namespace MinecraftClient.Mapping.EntityPalettes { public class EntityPalette119 : EntityPalette { - private static Dictionary mappings = new Dictionary(); + private static readonly Dictionary mappings = new(); static EntityPalette119() { diff --git a/MinecraftClient/Mapping/EntityTypeExtensions.cs b/MinecraftClient/Mapping/EntityTypeExtensions.cs index b022394b..e6546d22 100644 --- a/MinecraftClient/Mapping/EntityTypeExtensions.cs +++ b/MinecraftClient/Mapping/EntityTypeExtensions.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MinecraftClient.Mapping +namespace MinecraftClient.Mapping { public static class EntityTypeExtensions { diff --git a/MinecraftClient/Mapping/InteractType.cs b/MinecraftClient/Mapping/InteractType.cs index 02876e8f..f54a1014 100644 --- a/MinecraftClient/Mapping/InteractType.cs +++ b/MinecraftClient/Mapping/InteractType.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace MinecraftClient.Mapping +namespace MinecraftClient.Mapping { public enum InteractType { diff --git a/MinecraftClient/Mapping/Location.cs b/MinecraftClient/Mapping/Location.cs index 5852e6c6..069fdf32 100644 --- a/MinecraftClient/Mapping/Location.cs +++ b/MinecraftClient/Mapping/Location.cs @@ -1,8 +1,5 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Runtime.CompilerServices; -using System.Text; namespace MinecraftClient.Mapping { @@ -159,7 +156,7 @@ namespace MinecraftClient.Mapping /// New location public Location ToFloor() { - return new Location(Math.Floor(this.X), Math.Floor(this.Y), Math.Floor(this.Z)); + return new Location(Math.Floor(X), Math.Floor(Y), Math.Floor(Z)); } /// @@ -168,7 +165,7 @@ namespace MinecraftClient.Mapping /// New location public Location ToCenter() { - return new Location(Math.Floor(this.X) + 0.5, this.Y, Math.Floor(this.Z) + 0.5); + return new Location(Math.Floor(X) + 0.5, Y, Math.Floor(Z) + 0.5); } /// @@ -273,15 +270,15 @@ namespace MinecraftClient.Mapping /// /// Object to compare to /// TRUE if the locations are equals - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj == null) return false; - if (obj is Location) + if (obj is Location location) { - return ((int)this.X) == ((int)((Location)obj).X) - && ((int)this.Y) == ((int)((Location)obj).Y) - && ((int)this.Z) == ((int)((Location)obj).Z); + return ((int)X) == ((int)location.X) + && ((int)Y) == ((int)location.Y) + && ((int)Z) == ((int)location.Z); } return false; } @@ -293,6 +290,11 @@ namespace MinecraftClient.Mapping /// Second location to compare /// TRUE if the locations are equals public static bool operator ==(Location loc1, Location loc2) + { + return loc1.Equals(loc2); + } + + public static bool operator ==(Location? loc1, Location? loc2) { if (loc1 == null && loc2 == null) return true; @@ -308,6 +310,11 @@ namespace MinecraftClient.Mapping /// Second location to compare /// TRUE if the locations are equals public static bool operator !=(Location loc1, Location loc2) + { + return !loc1.Equals(loc2); + } + + public static bool operator !=(Location? loc1, Location? loc2) { if (loc1 == null && loc2 == null) return false; diff --git a/MinecraftClient/Mapping/MapIcon.cs b/MinecraftClient/Mapping/MapIcon.cs index 155f1b97..3862b8db 100644 --- a/MinecraftClient/Mapping/MapIcon.cs +++ b/MinecraftClient/Mapping/MapIcon.cs @@ -1,11 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using MinecraftClient.Protocol.Handlers; - -namespace MinecraftClient.Mapping +namespace MinecraftClient.Mapping { public class MapIcon { diff --git a/MinecraftClient/Mapping/MapIconType.cs b/MinecraftClient/Mapping/MapIconType.cs index 68a1e307..125527e5 100644 --- a/MinecraftClient/Mapping/MapIconType.cs +++ b/MinecraftClient/Mapping/MapIconType.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace MinecraftClient.Mapping +namespace MinecraftClient.Mapping { public enum MapIconType { diff --git a/MinecraftClient/Mapping/Material2Tool.cs b/MinecraftClient/Mapping/Material2Tool.cs index f2259d0f..d94315ab 100644 --- a/MinecraftClient/Mapping/Material2Tool.cs +++ b/MinecraftClient/Mapping/Material2Tool.cs @@ -1,5 +1,5 @@ -using MinecraftClient.Inventory; -using System.Collections.Generic; +using System.Collections.Generic; +using MinecraftClient.Inventory; namespace MinecraftClient.Mapping { @@ -8,7 +8,7 @@ namespace MinecraftClient.Mapping // Made with the following ressources: https://minecraft.fandom.com/wiki/Breaking // Sorted in alphabetical order. // Minable by Any Pickaxe. - private static readonly List pickaxeTier0 = new List() + private static readonly List pickaxeTier0 = new() { Material.ActivatorRail, Material.Andesite, @@ -281,7 +281,7 @@ namespace MinecraftClient.Mapping Material.YellowTerracotta, }; // Minable by Stone, iron, diamond, netherite. - private static readonly List pickaxeTier1 = new List() + private static readonly List pickaxeTier1 = new() { Material.CopperOre, Material.CopperBlock, @@ -329,7 +329,7 @@ namespace MinecraftClient.Mapping Material.WeatheredCutCopper, }; // Minable by Iron, diamond, netherite. - private static readonly List pickaxeTier2 = new List() + private static readonly List pickaxeTier2 = new() { Material.DeepslateDiamondOre, Material.DeepslateEmeraldOre, @@ -345,7 +345,7 @@ namespace MinecraftClient.Mapping Material.RedstoneOre, }; // Minable by Diamond, Netherite. - private static readonly List pickaxeTier3 = new List() + private static readonly List pickaxeTier3 = new() { Material.AncientDebris, Material.CryingObsidian, @@ -355,7 +355,7 @@ namespace MinecraftClient.Mapping }; // Every shovel can mine every block (speed difference). - private static readonly List shovel = new List() + private static readonly List shovel = new() { Material.BlackConcretePowder, Material.BlueConcretePowder, @@ -393,7 +393,7 @@ namespace MinecraftClient.Mapping Material.YellowConcretePowder, }; // Every axe can mine every block (speed difference). - private static readonly List axe = new List() + private static readonly List axe = new() { Material.AcaciaButton, Material.AcaciaDoor, @@ -578,7 +578,7 @@ namespace MinecraftClient.Mapping Material.YellowWallBanner, }; // Every block a shear can mine. - private static readonly List shears = new List() + private static readonly List shears = new() { Material.AcaciaLeaves, Material.AzaleaLeaves, @@ -607,7 +607,7 @@ namespace MinecraftClient.Mapping Material.YellowWool, }; // Every block that is mined with a sword. - private static readonly List sword = new List() + private static readonly List sword = new() { Material.Bamboo, Material.Cobweb, @@ -620,7 +620,7 @@ namespace MinecraftClient.Mapping Material.InfestedStoneBricks, }; // Every block that can be mined with a hoe. - private static readonly List hoe = new List() + private static readonly List hoe = new() { Material.AcaciaLeaves, Material.BirchLeaves, @@ -639,14 +639,14 @@ namespace MinecraftClient.Mapping Material.WetSponge, }; // Liquids - private static readonly List bucket = new List() + private static readonly List bucket = new() { Material.Lava, Material.Water }; // Unbreakable Blocks - private static readonly List unbreakable = new List() + private static readonly List unbreakable = new() { Material.Air, Material.Barrier, @@ -773,7 +773,7 @@ namespace MinecraftClient.Mapping ItemType.Bucket, }; } - else { return new ItemType[0]; } + else { return System.Array.Empty(); } } public static bool IsUnbreakable(Material block) { return unbreakable.Contains(block); } diff --git a/MinecraftClient/Mapping/MaterialExtensions.cs b/MinecraftClient/Mapping/MaterialExtensions.cs index f1b9129a..a3ff5592 100644 --- a/MinecraftClient/Mapping/MaterialExtensions.cs +++ b/MinecraftClient/Mapping/MaterialExtensions.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -namespace MinecraftClient.Mapping +namespace MinecraftClient.Mapping { /// /// Defines extension methods for the Material enumeration diff --git a/MinecraftClient/Mapping/Movement.cs b/MinecraftClient/Mapping/Movement.cs index 21811c8d..04cecd0e 100644 --- a/MinecraftClient/Mapping/Movement.cs +++ b/MinecraftClient/Mapping/Movement.cs @@ -23,7 +23,7 @@ namespace MinecraftClient.Mapping { if (Settings.GravityEnabled) { - Location onFoots = new Location(location.X, Math.Floor(location.Y), location.Z); + Location onFoots = new(location.X, Math.Floor(location.Y), location.Z); Location belowFoots = Move(location, Direction.Down); if (location.Y > Math.Truncate(location.Y) + 0.0001) { @@ -94,7 +94,7 @@ namespace MinecraftClient.Mapping { //Use MC-Like falling algorithm double Y = start.Y; - Queue fallSteps = new Queue(); + Queue fallSteps = new(); fallSteps.Enqueue(start); double motionPrev = motionY; motionY -= 0.08D; @@ -102,7 +102,7 @@ namespace MinecraftClient.Mapping Y += motionY; if (Y < goal.Y) return new Queue(new[] { goal }); - else + else return new Queue(new[] { new Location(start.X, Y, start.Z) }); } else @@ -120,7 +120,7 @@ namespace MinecraftClient.Mapping movementSteps.Enqueue(start + step * i); return movementSteps; } - else + else return new Queue(new[] { goal }); } } @@ -142,7 +142,7 @@ namespace MinecraftClient.Mapping /// A list of locations, or null if calculation failed public static Queue? CalculatePath(World world, Location start, Location goal, bool allowUnsafe, int maxOffset, int minOffset, TimeSpan timeout) { - CancellationTokenSource cts = new CancellationTokenSource(); + CancellationTokenSource cts = new(); Task?> pathfindingTask = Task.Factory.StartNew(() => Movement.CalculatePath(world, start, goal, allowUnsafe, maxOffset, minOffset, cts.Token)); pathfindingTask.Wait(timeout); if (!pathfindingTask.IsCompleted) @@ -171,7 +171,7 @@ namespace MinecraftClient.Mapping { // This is a bad configuration if (minOffset > maxOffset) - throw new ArgumentException("minOffset must be lower or equal to maxOffset", "minOffset"); + throw new ArgumentException("minOffset must be lower or equal to maxOffset", nameof(minOffset)); // Round start coordinates for easier calculation Location startLower = start.ToFloor(); @@ -184,18 +184,18 @@ namespace MinecraftClient.Mapping ///---/// // Prepare variables and datastructures for A* ///---/// - + // Dictionary that contains the relation between all coordinates and resolves the final path - Dictionary CameFrom = new Dictionary(); + Dictionary CameFrom = new(); // Create a Binary Heap for all open positions => Allows fast access to Nodes with lowest scores - BinaryHeap openSet = new BinaryHeap(); + BinaryHeap openSet = new(); // Dictionary to keep track of the G-Score of every location - Dictionary gScoreDict = new Dictionary(); + Dictionary gScoreDict = new(); // Set start values for variables openSet.Insert(0, (int)startLower.DistanceSquared(goalLower), startLower); gScoreDict[startLower] = 0; - BinaryHeap.Node current = null; + BinaryHeap.Node? current = null; ///---/// // Start of A* @@ -239,7 +239,7 @@ namespace MinecraftClient.Mapping } //// Goal could not be reached. Set the path to the closest location if close enough - if (current != null && (maxOffset == int.MaxValue || openSet.MinH_ScoreNode.H_score <= maxOffset)) + if (current != null && openSet.MinH_ScoreNode != null && (maxOffset == int.MaxValue || openSet.MinH_ScoreNode.H_score <= maxOffset)) return ReconstructPath(CameFrom, openSet.MinH_ScoreNode.Location, start, goal); else return null; @@ -306,17 +306,17 @@ namespace MinecraftClient.Mapping public Node(int g_score, int h_score, Location loc) { - this.G_score = g_score; - this.H_score = h_score; + G_score = g_score; + H_score = h_score; Location = loc; } } // List which contains all nodes in form of a Binary Heap - private List heapList; + private readonly List heapList; // Hashset for quick checks of locations included in the heap - private HashSet locationList; - public Node MinH_ScoreNode; + private readonly HashSet locationList; + public Node? MinH_ScoreNode; public BinaryHeap() { @@ -337,7 +337,7 @@ namespace MinecraftClient.Mapping int i = heapList.Count; // Temporarily save the node created with the parameters to allow comparisons - Node newNode = new Node(newG_Score, newH_Score, loc); + Node newNode = new(newG_Score, newH_Score, loc); // Add new note to the end of the list heapList.Add(newNode); @@ -384,7 +384,7 @@ namespace MinecraftClient.Mapping locationList.Remove(rootNode.Location); // Temporarirly store the last item's value. - Node lastNode = heapList[heapList.Count - 1]; + Node lastNode = heapList[^1]; // Remove the last value. heapList.RemoveAt(heapList.Count - 1); @@ -524,7 +524,7 @@ namespace MinecraftClient.Mapping public static bool IsSafe(World world, Location location) { return - //No block that can harm the player + //No block that can harm the player !world.GetBlock(location).Type.CanHarmPlayers() && !world.GetBlock(Move(location, Direction.Up)).Type.CanHarmPlayers() && !world.GetBlock(Move(location, Direction.Down)).Type.CanHarmPlayers() @@ -640,7 +640,7 @@ namespace MinecraftClient.Mapping return Move(Direction.North) + Move(Direction.West); default: - throw new ArgumentException("Unknown direction", "direction"); + throw new ArgumentException("Unknown direction", nameof(direction)); } } diff --git a/MinecraftClient/Mapping/World.cs b/MinecraftClient/Mapping/World.cs index ffe231ab..0e9a3241 100644 --- a/MinecraftClient/Mapping/World.cs +++ b/MinecraftClient/Mapping/World.cs @@ -2,8 +2,6 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading; namespace MinecraftClient.Mapping { @@ -23,7 +21,7 @@ namespace MinecraftClient.Mapping /// private static Dimension curDimension = new(); - private static Dictionary dimensionList = new(); + private static readonly Dictionary dimensionList = new(); /// /// Chunk data parsing progress @@ -62,10 +60,11 @@ namespace MinecraftClient.Mapping public static void StoreDimensionList(Dictionary registryCodec) { var dimensionListNbt = (object[])(((Dictionary)registryCodec["minecraft:dimension_type"])["value"]); - foreach (Dictionary dimensionNbt in dimensionListNbt) + foreach (var (dimensionName, dimensionType) in from Dictionary dimensionNbt in dimensionListNbt + let dimensionName = (string)dimensionNbt["name"] + let dimensionType = (Dictionary)dimensionNbt["element"] + select (dimensionName, dimensionType)) { - string dimensionName = (string)dimensionNbt["name"]; - Dictionary dimensionType = (Dictionary)dimensionNbt["element"]; StoreOneDimension(dimensionName, dimensionType); } } @@ -78,7 +77,7 @@ namespace MinecraftClient.Mapping public static void StoreOneDimension(string dimensionName, Dictionary dimensionType) { if (dimensionList.ContainsKey(dimensionName)) - dimensionList.Remove(dimensionName); + dimensionList.Remove(dimensionName); dimensionList.Add(dimensionName, new Dimension(dimensionName, dimensionType)); } @@ -170,16 +169,16 @@ namespace MinecraftClient.Mapping /// Block matching the specified block type public List FindBlock(Location from, Material block, int radiusx, int radiusy, int radiusz) { - Location minPoint = new Location(from.X - radiusx, from.Y - radiusy, from.Z - radiusz); - Location maxPoint = new Location(from.X + radiusx, from.Y + radiusy, from.Z + radiusz); - List list = new List { }; + Location minPoint = new(from.X - radiusx, from.Y - radiusy, from.Z - radiusz); + Location maxPoint = new(from.X + radiusx, from.Y + radiusy, from.Z + radiusz); + List list = new() { }; for (double x = minPoint.X; x <= maxPoint.X; x++) { for (double y = minPoint.Y; y <= maxPoint.Y; y++) { for (double z = minPoint.Z; z <= maxPoint.Z; z++) { - Location doneloc = new Location(x, y, z); + Location doneloc = new(x, y, z); Block doneblock = GetBlock(doneloc); Material blockType = doneblock.Type; if (blockType == block) @@ -218,5 +217,19 @@ namespace MinecraftClient.Mapping chunkCnt = 0; chunkLoadNotCompleted = 0; } + + public static string GetChunkLoadingStatus(World world) + { + double chunkLoadedRatio; + if (world.chunkCnt == 0) + chunkLoadedRatio = 0; + else + chunkLoadedRatio = (world.chunkCnt - world.chunkLoadNotCompleted) / (double)world.chunkCnt; + + string status = Translations.Get("cmd.move.chunk_loading_status", + chunkLoadedRatio, world.chunkCnt - world.chunkLoadNotCompleted, world.chunkCnt); + + return status; + } } } diff --git a/MinecraftClient/McClient.cs b/MinecraftClient/McClient.cs index 73213fbf..a8fed3b9 100644 --- a/MinecraftClient/McClient.cs +++ b/MinecraftClient/McClient.cs @@ -1,21 +1,19 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Net.Sockets; +using System.Text; using System.Threading; -using System.IO; -using System.Net; using MinecraftClient.ChatBots; -using MinecraftClient.Protocol; -using MinecraftClient.Proxy; -using MinecraftClient.Protocol.Handlers.Forge; -using MinecraftClient.Mapping; using MinecraftClient.Inventory; using MinecraftClient.Logger; +using MinecraftClient.Mapping; +using MinecraftClient.Protocol; +using MinecraftClient.Protocol.Handlers.Forge; using MinecraftClient.Protocol.Keys; -using MinecraftClient.Protocol.Session; using MinecraftClient.Protocol.Message; +using MinecraftClient.Protocol.Session; +using MinecraftClient.Proxy; namespace MinecraftClient { @@ -32,15 +30,15 @@ namespace MinecraftClient private static bool commandsLoaded = false; - private Queue chatQueue = new(); + private readonly Queue chatQueue = new(); private static DateTime nextMessageSendTime = DateTime.MinValue; - private Queue threadTasks = new(); - private object threadTasksLock = new(); + private readonly Queue threadTasks = new(); + private readonly object threadTasksLock = new(); private readonly List bots = new(); private static readonly List botsOnHold = new(); - private static Dictionary inventories = new(); + private static readonly Dictionary inventories = new(); private readonly Dictionary> registeredBotPluginChannels = new(); private readonly List registeredServerPluginChannels = new(); @@ -51,10 +49,10 @@ namespace MinecraftClient private bool inventoryHandlingRequested = false; private bool entityHandlingEnabled; - private object locationLock = new(); + private readonly object locationLock = new(); private bool locationReceived = false; - private World world = new(); - private Queue steps; + private readonly World world = new(); + private Queue? steps; private Queue? path; private Location location; private float? _yaw; // Used for calculation ONLY!!! Doesn't reflect the client yaw @@ -66,16 +64,16 @@ namespace MinecraftClient public int currentMovementSpeed = 4; private int sequenceId; // User for player block synchronization (Aka. digging, placing blocks, etc..) - private string host; - private int port; - private int protocolversion; - private string username; + private readonly string host; + private readonly int port; + private readonly int protocolversion; + private readonly string username; private Guid uuid; private string uuidStr; - private string sessionid; - private PlayerKeyPair? playerKeyPair; + private readonly string sessionid; + private readonly PlayerKeyPair? playerKeyPair; private DateTime lastKeepAlive; - private object lastKeepAliveLock = new(); + private readonly object lastKeepAliveLock = new(); private int respawnTicks = 0; private int gamemode = 0; private bool isSupportPreviewsChat; @@ -90,7 +88,7 @@ namespace MinecraftClient private byte CurrentSlot = 0; // Entity handling - private Dictionary entities = new(); + private readonly Dictionary entities = new(); // server TPS private long lastAge = 0; @@ -98,7 +96,7 @@ namespace MinecraftClient private double serverTPS = 0; private double averageTPS = 20; private const int maxSamples = 5; - private List tpsSamples = new(maxSamples); + private readonly List tpsSamples = new(maxSamples); private double sampleSum = 0; // ChatBot OnNetworkPacket event @@ -125,12 +123,12 @@ namespace MinecraftClient public int GetGamemode() { return gamemode; } public bool GetNetworkPacketCaptureEnabled() { return networkPacketCaptureEnabled; } public int GetProtocolVersion() { return protocolversion; } - public ILogger GetLogger() { return this.Log; } + public ILogger GetLogger() { return Log; } public int GetPlayerEntityID() { return playerEntityID; } public List GetLoadedChatBots() { return new List(bots); } - TcpClient client; - IMinecraftCom handler; + readonly TcpClient client; + readonly IMinecraftCom handler; CancellationTokenSource? cmdprompt = null; Tuple? timeoutdetector = null; @@ -152,18 +150,17 @@ namespace MinecraftClient inventoryHandlingEnabled = Settings.InventoryHandling; entityHandlingEnabled = Settings.EntityHandling; - bool retry = false; - this.sessionid = session.ID; - if (!Guid.TryParse(session.PlayerID, out this.uuid)) - this.uuid = Guid.Empty; - this.uuidStr = session.PlayerID; - this.username = session.PlayerName; - this.host = server_ip; + sessionid = session.ID; + if (!Guid.TryParse(session.PlayerID, out uuid)) + uuid = Guid.Empty; + uuidStr = session.PlayerID; + username = session.PlayerName; + host = server_ip; this.port = port; this.protocolversion = protocolversion; this.playerKeyPair = playerKeyPair; - this.Log = Settings.LogToFile + Log = Settings.LogToFile ? new FileLogLogger(Settings.ExpandVars(Settings.LogFile), Settings.PrependTimestamp) : new FilteredLogger(); Log.DebugEnabled = Settings.DebugMessages; @@ -183,7 +180,7 @@ namespace MinecraftClient try { - client = ProxyHandler.newTcpClient(host, port); + client = ProxyHandler.NewTcpClient(host, port); client.ReceiveBufferSize = 1024 * 1024; client.ReceiveTimeout = Settings.Timeout * 1000; // Default: 30 seconds handler = Protocol.ProtocolHandler.GetProtocolHandler(client, protocolversion, forgeInfo, this); @@ -225,45 +222,47 @@ namespace MinecraftClient else { Log.Error(Translations.Get("error.login_failed")); - retry = true; + goto Retry; } } catch (Exception e) { Log.Error(e.GetType().Name + ": " + e.Message); Log.Error(Translations.Get("error.join")); - retry = true; + goto Retry; } } catch (SocketException e) { Log.Error(e.Message); Log.Error(Translations.Get("error.connect")); - retry = true; + goto Retry; } - if (retry) + return; + + Retry: + if (timeoutdetector != null) { - if (timeoutdetector != null) - { - timeoutdetector.Item2.Cancel(); - timeoutdetector = null; - } - if (ReconnectionAttemptsLeft > 0) - { - Log.Info(Translations.Get("mcc.reconnect", ReconnectionAttemptsLeft)); - Thread.Sleep(5000); - ReconnectionAttemptsLeft--; - Program.Restart(); - } - else if (command == null && Settings.interactiveMode) - { - ConsoleInteractive.ConsoleReader.StopReadThread(); - ConsoleInteractive.ConsoleReader.MessageReceived -= ConsoleReaderOnMessageReceived; - ConsoleInteractive.ConsoleReader.OnKeyInput -= ConsoleIO.AutocompleteHandler; - Program.HandleFailure(); - } + timeoutdetector.Item2.Cancel(); + timeoutdetector = null; } + if (ReconnectionAttemptsLeft > 0) + { + Log.Info(Translations.Get("mcc.reconnect", ReconnectionAttemptsLeft)); + Thread.Sleep(5000); + ReconnectionAttemptsLeft--; + Program.Restart(); + } + else if (command == null && Settings.interactiveMode) + { + ConsoleInteractive.ConsoleReader.StopReadThread(); + ConsoleInteractive.ConsoleReader.MessageReceived -= ConsoleReaderOnMessageReceived; + ConsoleInteractive.ConsoleReader.OnKeyInput -= ConsoleIO.AutocompleteHandler; + Program.HandleFailure(); + } + + throw new Exception("Initialization failed."); } /// @@ -502,7 +501,7 @@ namespace MinecraftClient } //Process AutoRelog last to make sure other bots can perform their cleanup tasks first (issue #1517) - List onDisconnectBotList = bots.Where(bot => !(bot is AutoRelog)).ToList(); + List onDisconnectBotList = bots.Where(bot => bot is not AutoRelog).ToList(); onDisconnectBotList.AddRange(bots.Where(bot => bot is AutoRelog)); foreach (ChatBot bot in onDisconnectBotList) @@ -513,7 +512,7 @@ namespace MinecraftClient } catch (Exception e) { - if (!(e is ThreadAbortException)) + if (e is not ThreadAbortException) { Log.Warn("OnDisconnect: Got error from " + bot.ToString() + ": " + e.ToString()); } @@ -576,13 +575,13 @@ namespace MinecraftClient { if (Settings.internalCmdChar == ' ' || text[0] == Settings.internalCmdChar) { - string response_msg = ""; - string command = Settings.internalCmdChar == ' ' ? text : text.Substring(1); + string? response_msg = ""; + string command = Settings.internalCmdChar == ' ' ? text : text[1..]; if (!PerformInternalCommand(Settings.ExpandVars(command), ref response_msg, Settings.GetVariables()) && Settings.internalCmdChar == '/') { SendText(text); } - else if (response_msg.Length > 0) + else if (!String.IsNullOrEmpty(response_msg)) { Log.Info(response_msg); } @@ -641,16 +640,16 @@ namespace MinecraftClient /// May contain a confirmation or error message after processing the command, or "" otherwise. /// Local variables passed along with the command /// TRUE if the command was indeed an internal MCC command - public bool PerformInternalCommand(string command, ref string response_msg, Dictionary? localVars = null) + public bool PerformInternalCommand(string command, ref string? response_msg, Dictionary? localVars = null) { /* Process the provided command */ string command_name = command.Split(' ')[0].ToLower(); if (command_name == "help") { - if (Command.hasArg(command)) + if (Command.HasArg(command)) { - string help_cmdname = Command.getArgs(command)[0].ToLower(); + string help_cmdname = Command.GetArgs(command)[0].ToLower(); if (help_cmdname == "help") { response_msg = Translations.Get("icmd.help"); @@ -671,13 +670,13 @@ namespace MinecraftClient { try { - bot.OnInternalCommand(command_name, string.Join(" ", Command.getArgs(command)), response_msg); + bot.OnInternalCommand(command_name, string.Join(" ", Command.GetArgs(command)), response_msg); } catch (Exception e) { - if (!(e is ThreadAbortException)) + if (e is not ThreadAbortException) { - Log.Warn(Translations.Get("icmd.error", bot.ToString(), e.ToString())); + Log.Warn(Translations.Get("icmd.error", bot.ToString() ?? string.Empty, e.ToString())); } else throw; //ThreadAbortException should not be caught } @@ -705,10 +704,10 @@ namespace MinecraftClient { try { - Command cmd = (Command)Activator.CreateInstance(type); + Command cmd = (Command)Activator.CreateInstance(type)!; cmds[Settings.ToLowerIfNeed(cmd.CmdName)] = cmd; cmd_names.Add(Settings.ToLowerIfNeed(cmd.CmdName)); - foreach (string alias in cmd.getCMDAliases()) + foreach (string alias in cmd.GetCMDAliases()) cmds[Settings.ToLowerIfNeed(alias)] = cmd; } catch (Exception e) @@ -773,7 +772,7 @@ namespace MinecraftClient } else { - TaskWithResult taskWithResult = new TaskWithResult(task); + TaskWithResult taskWithResult = new(task); lock (threadTasksLock) { threadTasks.Enqueue(taskWithResult.ExecuteSynchronously); @@ -813,7 +812,7 @@ namespace MinecraftClient { get { - int callingThreadId = Thread.CurrentThread.ManagedThreadId; + int callingThreadId = Environment.CurrentManagedThreadId; if (handler != null) { return handler.GetNetMainThreadId() != callingThreadId; @@ -845,7 +844,7 @@ namespace MinecraftClient bots.Add(b); if (init) DispatchBotEvent(bot => bot.Initialize(), new ChatBot[] { b }); - if (this.handler != null) + if (handler != null) DispatchBotEvent(bot => bot.AfterGameJoined(), new ChatBot[] { b }); Settings.SingleCommand = ""; } @@ -1109,7 +1108,7 @@ namespace MinecraftClient /// Dictionay of online players, key is UUID, value is Player name public Dictionary GetOnlinePlayersWithUUID() { - Dictionary uuid2Player = new Dictionary(); + Dictionary uuid2Player = new(); lock (onlinePlayers) { foreach (Guid key in onlinePlayers.Keys) @@ -1165,7 +1164,7 @@ namespace MinecraftClient else { // Calculate path through pathfinding. Path contains a list of 1-block movement that will be divided into steps - path = Movement.CalculatePath(world, this.location, goal, allowUnsafe, maxOffset, minOffset, timeout ?? TimeSpan.FromSeconds(5)); + path = Movement.CalculatePath(world, location, goal, allowUnsafe, maxOffset, minOffset, timeout ?? TimeSpan.FromSeconds(5)); return path != null; } } @@ -1241,8 +1240,10 @@ namespace MinecraftClient } else { - List bots = new List(); - bots.Add(bot); + List bots = new() + { + bot + }; registeredBotPluginChannels[channel] = bots; SendPluginChannelMessage("REGISTER", Encoding.UTF8.GetBytes(channel), true); } @@ -1315,7 +1316,7 @@ namespace MinecraftClient /// TRUE if the item was successfully used public bool UseItemOnHand() { - return InvokeOnMainThread(() => handler.SendUseItem(0, this.sequenceId)); + return InvokeOnMainThread(() => handler.SendUseItem(0, sequenceId)); } /// @@ -1324,7 +1325,7 @@ namespace MinecraftClient /// TRUE if the item was successfully used public bool UseItemOnLeftHand() { - return InvokeOnMainThread(() => handler.SendUseItem(1, this.sequenceId)); + return InvokeOnMainThread(() => handler.SendUseItem(1, sequenceId)); } /// @@ -1437,9 +1438,7 @@ namespace MinecraftClient else { // Swap two items - var itemTmp = playerInventory.Items[-1]; - playerInventory.Items[-1] = inventory.Items[slotId]; - inventory.Items[slotId] = itemTmp; + (inventory.Items[slotId], playerInventory.Items[-1]) = (playerInventory.Items[-1], inventory.Items[slotId]); } } else @@ -1494,16 +1493,14 @@ namespace MinecraftClient else { // Swap two items - var itemTmp = playerInventory.Items[-1]; - playerInventory.Items[-1] = inventory.Items[slotId]; - inventory.Items[slotId] = itemTmp; + (inventory.Items[slotId], playerInventory.Items[-1]) = (playerInventory.Items[-1], inventory.Items[slotId]); } } else { // Drop 1 item count from cursor - var itemTmp = playerInventory.Items[-1]; - var itemClone = new Item(itemTmp.Type, 1, itemTmp.NBT); + Item itemTmp = playerInventory.Items[-1]; + Item itemClone = new(itemTmp.Type, 1, itemTmp.NBT); inventory.Items[slotId] = itemClone; playerInventory.Items[-1].Count--; } @@ -1871,7 +1868,7 @@ namespace MinecraftClient break; case ContainerType.Lectern: return false; - break; + // break; case ContainerType.Loom: if (slotId >= 0 && slotId <= 3) { @@ -2213,7 +2210,7 @@ namespace MinecraftClient /// TRUE if successfully placed public bool PlaceBlock(Location location, Direction blockFace, Hand hand = Hand.MainHand) { - return InvokeOnMainThread(() => handler.SendPlayerBlockPlacement((int)hand, location, blockFace, this.sequenceId)); + return InvokeOnMainThread(() => handler.SendPlayerBlockPlacement((int)hand, location, blockFace, sequenceId)); } /// @@ -2239,9 +2236,9 @@ namespace MinecraftClient // Send dig start and dig end, will need to wait for server response to know dig result // See https://wiki.vg/How_to_Write_a_Client#Digging for more details - return handler.SendPlayerDigging(0, location, blockFace, this.sequenceId) + return handler.SendPlayerDigging(0, location, blockFace, sequenceId) && (!swingArms || DoAnimation((int)Hand.MainHand)) - && handler.SendPlayerDigging(2, location, blockFace, this.sequenceId); + && handler.SendPlayerDigging(2, location, blockFace, sequenceId); } /// @@ -2364,11 +2361,11 @@ namespace MinecraftClient } catch (Exception e) { - if (!(e is ThreadAbortException)) + if (e is not ThreadAbortException) { //Retrieve parent method name to determine which event caused the exception - System.Diagnostics.StackFrame frame = new System.Diagnostics.StackFrame(1); - System.Reflection.MethodBase method = frame.GetMethod(); + System.Diagnostics.StackFrame frame = new(1); + System.Reflection.MethodBase method = frame.GetMethod()!; string parentMethodName = method.Name; //Display a meaningful error message to help debugging the ChatBot @@ -2464,7 +2461,7 @@ namespace MinecraftClient /// Current goal of movement. Location.Zero if not set. public Location GetCurrentMovementGoal() { - return ClientIsMoving() ? Location.Zero : path.Last(); + return (ClientIsMoving() || path == null) ? Location.Zero : path.Last(); } /// @@ -2529,8 +2526,8 @@ namespace MinecraftClient /// Pitch to look at public void UpdateLocation(Location location, float yaw, float pitch) { - this._yaw = yaw; - this._pitch = pitch; + _yaw = yaw; + _pitch = pitch; UpdateLocation(location, false); } @@ -2586,7 +2583,7 @@ namespace MinecraftClient case Direction.South: break; default: - throw new ArgumentException(Translations.Get("exception.unknown_direction"), "direction"); + throw new ArgumentException(Translations.Get("exception.unknown_direction"), nameof(direction)); } UpdateLocation(location, yaw, pitch); @@ -2694,7 +2691,7 @@ namespace MinecraftClient /// Window ID /// Slot ID /// Item (may be null for empty slot) - public void OnSetSlot(byte inventoryID, short slotID, Item item, int stateId) + public void OnSetSlot(byte inventoryID, short slotID, Item? item, int stateId) { if (inventories.ContainsKey(inventoryID)) inventories[inventoryID].StateID = stateId; @@ -2751,8 +2748,8 @@ namespace MinecraftClient if (player.Name == username) { // 1.19+ offline server is possible to return different uuid - this.uuid = player.Uuid; - this.uuidStr = player.Uuid.ToString().Replace("-", string.Empty); + uuid = player.Uuid; + uuidStr = player.Uuid.ToString().Replace("-", string.Empty); } lock (onlinePlayers) @@ -2860,7 +2857,7 @@ namespace MinecraftClient /// Entity ID /// Equipment slot. 0: main hand, 1: off hand, 2–5: armor slot (2: boots, 3: leggings, 4: chestplate, 5: helmet) /// Item) - public void OnEntityEquipment(int entityid, int slot, Item item) + public void OnEntityEquipment(int entityid, int slot, Item? item) { if (entities.ContainsKey(entityid)) { @@ -2889,7 +2886,7 @@ namespace MinecraftClient if (onlinePlayers.ContainsKey(uuid)) { string playerName = onlinePlayers[uuid].Name; - if (playerName == this.username) + if (playerName == username) this.gamemode = gamemode; DispatchBotEvent(bot => bot.OnGamemodeUpdate(playerName, uuid, gamemode)); } @@ -2944,7 +2941,7 @@ namespace MinecraftClient { if (entities.ContainsKey(EntityID)) { - Location location = new Location(X, Y, Z); + Location location = new(X, Y, Z); entities[EntityID].Location = location; DispatchBotEvent(bot => bot.OnEntityMove(entities[EntityID])); } @@ -3200,13 +3197,13 @@ namespace MinecraftClient } if (metadata.TryGetValue(2, out object? nameObj) && nameObj != null && nameObj.GetType() == typeof(string)) { - string name = nameObj.ToString()!; + string name = nameObj.ToString() ?? string.Empty; entity.CustomNameJson = name; entity.CustomName = ChatParser.ParseText(name); } if (metadata.TryGetValue(3, out object? nameVisableObj) && nameVisableObj != null && nameVisableObj.GetType() == typeof(bool)) { - entity.IsCustomNameVisible = bool.Parse(nameVisableObj.ToString()!); + entity.IsCustomNameVisible = bool.Parse(nameVisableObj.ToString() ?? string.Empty); } DispatchBotEvent(bot => bot.OnEntityMetadata(entity, metadata)); } @@ -3271,7 +3268,7 @@ namespace MinecraftClient /// Indicates if the server previews chat public void OnServerDataRecived(bool hasMotd, string motd, bool hasIcon, string iconBase64, bool previewsChat) { - this.isSupportPreviewsChat = previewsChat; + isSupportPreviewsChat = previewsChat; } /// @@ -3280,7 +3277,7 @@ namespace MinecraftClient /// Indicates if the server previews chat public void OnChatPreviewSettingUpdate(bool previewsChat) { - this.isSupportPreviewsChat = previewsChat; + isSupportPreviewsChat = previewsChat; } /// diff --git a/MinecraftClient/MinecraftClient.csproj b/MinecraftClient/MinecraftClient.csproj index 794364ff..7148da0b 100644 --- a/MinecraftClient/MinecraftClient.csproj +++ b/MinecraftClient/MinecraftClient.csproj @@ -1,4 +1,4 @@ - + net6.0 Exe @@ -18,6 +18,11 @@ MinecraftClient.Program + + + + + @@ -28,16 +33,16 @@ - + + - + - - all - - + + NU1701 + diff --git a/MinecraftClient/Program.cs b/MinecraftClient/Program.cs index 14281da5..2eedb89a 100644 --- a/MinecraftClient/Program.cs +++ b/MinecraftClient/Program.cs @@ -1,22 +1,20 @@ using System; -using System.IO; using System.Collections.Generic; +using System.IO; using System.Linq; -using System.Text; -using MinecraftClient.Protocol; using System.Reflection; using System.Runtime.InteropServices; +using System.Text; using System.Threading; -using MinecraftClient.Protocol.Handlers.Forge; -using MinecraftClient.Protocol.Session; -using MinecraftClient.Mapping.EntityPalettes; -using MinecraftClient.Mapping.BlockPalettes; -using MinecraftClient.Inventory.ItemPalettes; -using MinecraftClient.WinAPI; -using MinecraftClient.Protocol.Keys; -using System.Security.Cryptography; -using System.Xml.Linq; using System.Threading.Tasks; +using MinecraftClient.Inventory.ItemPalettes; +using MinecraftClient.Mapping.BlockPalettes; +using MinecraftClient.Mapping.EntityPalettes; +using MinecraftClient.Protocol; +using MinecraftClient.Protocol.Handlers.Forge; +using MinecraftClient.Protocol.Keys; +using MinecraftClient.Protocol.Session; +using MinecraftClient.WinAPI; namespace MinecraftClient { @@ -36,13 +34,13 @@ namespace MinecraftClient /// static class Program { - private static McClient client; - public static string[] startupargs; + private static McClient? client; + public static string[]? startupargs; public const string Version = MCHighestVersion; public const string MCLowestVersion = "1.4.6"; public const string MCHighestVersion = "1.19.2"; - public static readonly string BuildInfo = null; + public static readonly string? BuildInfo = null; private static Tuple? offlinePrompt = null; private static bool useMcVersionOnce = false; @@ -77,14 +75,14 @@ namespace MinecraftClient //Setup ConsoleIO ConsoleIO.LogPrefix = "§8[MCC] "; - if (args.Length >= 1 && args[args.Length - 1] == "BasicIO" || args.Length >= 1 && args[args.Length - 1] == "BasicIO-NoColor") + if (args.Length >= 1 && args[^1] == "BasicIO" || args.Length >= 1 && args[^1] == "BasicIO-NoColor") { - if (args.Length >= 1 && args[args.Length - 1] == "BasicIO-NoColor") + if (args.Length >= 1 && args[^1] == "BasicIO-NoColor") { ConsoleIO.BasicIO_NoColor = true; } ConsoleIO.BasicIO = true; - args = args.Where(o => !Object.ReferenceEquals(o, args[args.Length - 1])).ToArray(); + args = args.Where(o => !Object.ReferenceEquals(o, args[^1])).ToArray(); } if (!ConsoleIO.BasicIO) @@ -150,10 +148,10 @@ namespace MinecraftClient { if (argument.StartsWith("--") && !argument.Contains("--generate")) { - if (!argument.Contains("=")) + if (!argument.Contains('=')) throw new ArgumentException(Translations.Get("error.setting.argument_syntax", argument)); - string[] argParts = argument.Substring(2).Split('='); + string[] argParts = argument[2..].Split('='); string argName = argParts[0].Trim(); string argValue = argParts[1].Replace("\"", "").Trim(); @@ -269,7 +267,7 @@ namespace MinecraftClient // Do NOT use Program.Exit() as creating new Thread cause program to freeze if (client != null) { client.Disconnect(); ConsoleIO.Reset(); } if (offlinePrompt != null) { offlinePrompt.Item2.Cancel(); offlinePrompt = null; ConsoleIO.Reset(); } - if (Settings.playerHeadAsIcon) { ConsoleIcon.revertToMCCIcon(); } + if (Settings.playerHeadAsIcon) { ConsoleIcon.RevertToMCCIcon(); } }); @@ -293,7 +291,7 @@ namespace MinecraftClient /// private static void InitializeClient() { - SessionToken session = new SessionToken(); + SessionToken session = new(); PlayerKeyPair? playerKeyPair = null; ProtocolHandler.LoginResult result = ProtocolHandler.LoginResult.LoginRequired; @@ -390,12 +388,12 @@ namespace MinecraftClient Console.Title = Settings.ExpandVars(Settings.ConsoleTitle); if (Settings.playerHeadAsIcon) - ConsoleIcon.setPlayerIconAsync(Settings.Username); + ConsoleIcon.SetPlayerIconAsync(Settings.Username); if (Settings.DebugMessages) Translations.WriteLine("debug.session_id", session.ID); - List availableWorlds = new List(); + List availableWorlds = new(); if (Settings.MinecraftRealmsEnabled && !String.IsNullOrEmpty(session.ID)) availableWorlds = ProtocolHandler.RealmsListWorlds(Settings.Username, session.PlayerID, session.ID); @@ -412,9 +410,8 @@ namespace MinecraftClient HandleFailure(Translations.Get("error.realms.access_denied"), false, ChatBot.DisconnectReason.LoginRejected); return; } - int worldIndex = 0; string worldId = addressInput.Split(':')[1]; - if (!availableWorlds.Contains(worldId) && int.TryParse(worldId, out worldIndex) && worldIndex < availableWorlds.Count) + if (!availableWorlds.Contains(worldId) && int.TryParse(worldId, out int worldIndex) && worldIndex < availableWorlds.Count) worldId = availableWorlds[worldIndex]; if (availableWorlds.Contains(worldId)) { @@ -508,7 +505,11 @@ namespace MinecraftClient if (Settings.ConsoleTitle != "") Console.Title = Settings.ExpandVars(Settings.ConsoleTitle); } - catch (NotSupportedException) { HandleFailure(Translations.Get("error.unsupported"), true); } + catch (NotSupportedException) + { + HandleFailure(Translations.Get("error.unsupported"), true); + } + catch (Exception) { } } else HandleFailure(Translations.Get("error.determine"), true); } @@ -516,18 +517,20 @@ namespace MinecraftClient { string failureMessage = Translations.Get("error.login"); string failureReason = ""; - switch (result) + failureReason = result switch { - case ProtocolHandler.LoginResult.AccountMigrated: failureReason = "error.login.migrated"; break; - case ProtocolHandler.LoginResult.ServiceUnavailable: failureReason = "error.login.server"; break; - case ProtocolHandler.LoginResult.WrongPassword: failureReason = "error.login.blocked"; break; - case ProtocolHandler.LoginResult.InvalidResponse: failureReason = "error.login.response"; break; - case ProtocolHandler.LoginResult.NotPremium: failureReason = "error.login.premium"; break; - case ProtocolHandler.LoginResult.OtherError: failureReason = "error.login.network"; break; - case ProtocolHandler.LoginResult.SSLError: failureReason = "error.login.ssl"; break; - case ProtocolHandler.LoginResult.UserCancel: failureReason = "error.login.cancel"; break; - default: failureReason = "error.login.unknown"; break; - } +#pragma warning disable format // @formatter:off + ProtocolHandler.LoginResult.AccountMigrated => "error.login.migrated", + ProtocolHandler.LoginResult.ServiceUnavailable => "error.login.server", + ProtocolHandler.LoginResult.WrongPassword => "error.login.blocked", + ProtocolHandler.LoginResult.InvalidResponse => "error.login.response", + ProtocolHandler.LoginResult.NotPremium => "error.login.premium", + ProtocolHandler.LoginResult.OtherError => "error.login.network", + ProtocolHandler.LoginResult.SSLError => "error.login.ssl", + ProtocolHandler.LoginResult.UserCancel => "error.login.cancel", + _ => "error.login.unknown", +#pragma warning restore format // @formatter:on + }; failureMessage += Translations.Get(failureReason); HandleFailure(failureMessage, false, ChatBot.DisconnectReason.LoginRejected); } @@ -572,7 +575,7 @@ namespace MinecraftClient { if (client != null) { client.Disconnect(); ConsoleIO.Reset(); } if (offlinePrompt != null) { offlinePrompt.Item2.Cancel(); offlinePrompt.Item1.Join(); offlinePrompt = null; ConsoleIO.Reset(); } - if (Settings.playerHeadAsIcon) { ConsoleIcon.revertToMCCIcon(); } + if (Settings.playerHeadAsIcon) { ConsoleIcon.RevertToMCCIcon(); } Environment.Exit(exitcode); })).Start(); } @@ -584,7 +587,7 @@ namespace MinecraftClient /// Error message to display and optionally pass to AutoRelog bot /// Specify if the error is related to an incompatible or unkown server version /// If set, the error message will be processed by the AutoRelog bot - public static void HandleFailure(string errorMessage = null, bool versionError = false, ChatBots.AutoRelog.DisconnectReason? disconnectReason = null) + public static void HandleFailure(string? errorMessage = null, bool versionError = false, ChatBots.AutoRelog.DisconnectReason? disconnectReason = null) { if (!String.IsNullOrEmpty(errorMessage)) { @@ -643,7 +646,7 @@ namespace MinecraftClient if (Settings.internalCmdChar != ' ' && command[0] == Settings.internalCmdChar) - command = command.Substring(1); + command = command[1..]; if (command.StartsWith("reco")) { @@ -722,7 +725,7 @@ namespace MinecraftClient /// Namespace to process /// Assembly to use. Default is Assembly.GetExecutingAssembly() /// - public static Type[] GetTypesInNamespace(string nameSpace, Assembly assembly = null) + public static Type[] GetTypesInNamespace(string nameSpace, Assembly? assembly = null) { if (assembly == null) { assembly = Assembly.GetExecutingAssembly(); } return assembly.GetTypes().Where(t => String.Equals(t.Namespace, nameSpace, StringComparison.Ordinal)).ToArray(); @@ -733,12 +736,10 @@ namespace MinecraftClient /// static Program() { - AssemblyConfigurationAttribute attribute - = typeof(Program) + if (typeof(Program) .Assembly .GetCustomAttributes(typeof(System.Reflection.AssemblyConfigurationAttribute), false) - .FirstOrDefault() as AssemblyConfigurationAttribute; - if (attribute != null) + .FirstOrDefault() is AssemblyConfigurationAttribute attribute) BuildInfo = attribute.Configuration; } } diff --git a/MinecraftClient/Properties/AssemblyInfo.cs b/MinecraftClient/Properties/AssemblyInfo.cs index 81eee9c1..99b66052 100644 --- a/MinecraftClient/Properties/AssemblyInfo.cs +++ b/MinecraftClient/Properties/AssemblyInfo.cs @@ -1,5 +1,4 @@ using System.Reflection; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/MinecraftClient/Protocol/DataTypeGenerator.cs b/MinecraftClient/Protocol/DataTypeGenerator.cs index f0070523..039ae477 100644 --- a/MinecraftClient/Protocol/DataTypeGenerator.cs +++ b/MinecraftClient/Protocol/DataTypeGenerator.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; using System.IO; +using System.Linq; namespace MinecraftClient.Protocol { @@ -22,7 +22,7 @@ namespace MinecraftClient.Protocol { Json.JSONData rawJson = Json.ParseJson(File.ReadAllText(registriesJsonFile)); Json.JSONData rawRegistry = rawJson.Properties[jsonRegistryName].Properties["entries"]; - Dictionary registry = new Dictionary(); + Dictionary registry = new(); foreach (KeyValuePair entry in rawRegistry.Properties) { @@ -32,7 +32,7 @@ namespace MinecraftClient.Protocol string entryName = String.Concat( entry.Key.Replace("minecraft:", "") .Split('_') - .Select(word => char.ToUpper(word[0]) + word.Substring(1)) + .Select(word => char.ToUpper(word[0]) + word[1..]) ); if (registry.ContainsKey(entryId)) @@ -53,7 +53,7 @@ namespace MinecraftClient.Protocol /// Output enum namespace, e.g. MinecraftClient.Inventory public static void GenerateEnum(string registriesJsonFile, string jsonRegistryName, string outputEnum, string enumNamespace) { - List outputEnumLines = new List(); + List outputEnumLines = new(); outputEnumLines.AddRange(new[] { "namespace " + enumNamespace, @@ -71,7 +71,7 @@ namespace MinecraftClient.Protocol "}" }); - string outputEnumPath = Path.Combine(Path.GetDirectoryName(registriesJsonFile), outputEnum + "XXX.cs"); + string outputEnumPath = Path.Combine(Path.GetDirectoryName(registriesJsonFile)!, outputEnum + "XXX.cs"); File.WriteAllLines(outputEnumPath, outputEnumLines); } @@ -86,8 +86,8 @@ namespace MinecraftClient.Protocol /// Palette namespace, e.g. MinecraftClient.EntityPalettes public static void GenerateEnumWithPalette(string registriesJsonFile, string jsonRegistryName, string outputEnum, string enumNamespace, string outputPalette, string paletteNamespace) { - List outputEnumLines = new List(); - List outputPaletteLines = new List(); + List outputEnumLines = new(); + List outputPaletteLines = new(); outputEnumLines.AddRange(new[] { "namespace " + enumNamespace, @@ -97,14 +97,13 @@ namespace MinecraftClient.Protocol }); outputPaletteLines.AddRange(new[] { - "using System;", "using System.Collections.Generic;", "", "namespace " + paletteNamespace, "{", " public class " + outputPalette + "XXX : " + outputPalette, " {", - " private static Dictionary mappings = new Dictionary();", + " private static readonly Dictionary mappings = new();", "", " static " + outputPalette + "XXX()", " {", @@ -134,8 +133,8 @@ namespace MinecraftClient.Protocol "}" }); - string outputEnumPath = Path.Combine(Path.GetDirectoryName(registriesJsonFile), outputEnum + "XXX.cs"); - string outputPalettePath = Path.Combine(Path.GetDirectoryName(registriesJsonFile), outputPalette + "XXX.cs"); + string outputEnumPath = Path.Combine(Path.GetDirectoryName(registriesJsonFile)!, outputEnum + "XXX.cs"); + string outputPalettePath = Path.Combine(Path.GetDirectoryName(registriesJsonFile)!, outputPalette + "XXX.cs"); File.WriteAllLines(outputEnumPath, outputEnumLines); File.WriteAllLines(outputPalettePath, outputPaletteLines); diff --git a/MinecraftClient/Protocol/EntityActionType.cs b/MinecraftClient/Protocol/EntityActionType.cs index bda20370..b7191ded 100644 --- a/MinecraftClient/Protocol/EntityActionType.cs +++ b/MinecraftClient/Protocol/EntityActionType.cs @@ -1,8 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - namespace MinecraftClient.Protocol { public enum EntityActionType diff --git a/MinecraftClient/Protocol/GuidExtensions.cs b/MinecraftClient/Protocol/GuidExtensions.cs index f148c2af..c5ce2645 100644 --- a/MinecraftClient/Protocol/GuidExtensions.cs +++ b/MinecraftClient/Protocol/GuidExtensions.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient.Protocol { diff --git a/MinecraftClient/Protocol/Handlers/Compression/CRC32.cs b/MinecraftClient/Protocol/Handlers/Compression/CRC32.cs deleted file mode 100644 index 97593b91..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/CRC32.cs +++ /dev/null @@ -1,814 +0,0 @@ -// CRC32.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 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: <2011-August-02 18:25:54> -// -// ------------------------------------------------------------------ -// -// This module defines the CRC32 class, which can do the CRC32 algorithm, using -// arbitrary starting polynomials, and bit reversal. The bit reversal is what -// distinguishes this CRC-32 used in BZip2 from the CRC-32 that is used in PKZIP -// files, or GZIP files. This class does both. -// -// ------------------------------------------------------------------ - - -using System; -using Interop = System.Runtime.InteropServices; - -namespace Ionic.Crc -{ - /// - /// Computes a CRC-32. The CRC-32 algorithm is parameterized - you - /// can set the polynomial and enable or disable bit - /// reversal. This can be used for GZIP, BZip2, or ZIP. - /// - /// - /// This type is used internally by DotNetZip; it is generally not used - /// directly by applications wishing to create, read, or manipulate zip - /// archive files. - /// - - [Interop.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d0000C")] - [Interop.ComVisible(true)] -#if !NETCF - [Interop.ClassInterface(Interop.ClassInterfaceType.AutoDispatch)] -#endif - public class CRC32 - { - /// - /// Indicates the total number of bytes applied to the CRC. - /// - public Int64 TotalBytesRead - { - get - { - return _TotalBytesRead; - } - } - - /// - /// Indicates the current CRC for all blocks slurped in. - /// - public Int32 Crc32Result - { - get - { - return unchecked((Int32)(~_register)); - } - } - - /// - /// Returns the CRC32 for the specified stream. - /// - /// The stream over which to calculate the CRC32 - /// the CRC32 calculation - public Int32 GetCrc32(System.IO.Stream input) - { - return GetCrc32AndCopy(input, null); - } - - /// - /// Returns the CRC32 for the specified stream, and writes the input into the - /// output stream. - /// - /// The stream over which to calculate the CRC32 - /// The stream into which to deflate the input - /// the CRC32 calculation - public Int32 GetCrc32AndCopy(System.IO.Stream input, System.IO.Stream output) - { - if (input == null) - throw new Exception("The input stream must not be null."); - - unchecked - { - byte[] buffer = new byte[BUFFER_SIZE]; - int readSize = BUFFER_SIZE; - - _TotalBytesRead = 0; - int count = input.Read(buffer, 0, readSize); - if (output != null) output.Write(buffer, 0, count); - _TotalBytesRead += count; - while (count > 0) - { - SlurpBlock(buffer, 0, count); - count = input.Read(buffer, 0, readSize); - if (output != null) output.Write(buffer, 0, count); - _TotalBytesRead += count; - } - - return (Int32)(~_register); - } - } - - - /// - /// Get the CRC32 for the given (word,byte) combo. This is a - /// computation defined by PKzip for PKZIP 2.0 (weak) encryption. - /// - /// The word to start with. - /// The byte to combine it with. - /// The CRC-ized result. - public Int32 ComputeCrc32(Int32 W, byte B) - { - return _InternalComputeCrc32((UInt32)W, B); - } - - internal Int32 _InternalComputeCrc32(UInt32 W, byte B) - { - return (Int32)(crc32Table[(W ^ B) & 0xFF] ^ (W >> 8)); - } - - - /// - /// Update the value for the running CRC32 using the given block of bytes. - /// This is useful when using the CRC32() class in a Stream. - /// - /// block of bytes to slurp - /// starting point in the block - /// how many bytes within the block to slurp - public void SlurpBlock(byte[] block, int offset, int count) - { - if (block == null) - throw new Exception("The data buffer must not be null."); - - // bzip algorithm - for (int i = 0; i < count; i++) - { - int x = offset + i; - byte b = block[x]; - if (this.reverseBits) - { - UInt32 temp = (_register >> 24) ^ b; - _register = (_register << 8) ^ crc32Table[temp]; - } - else - { - UInt32 temp = (_register & 0x000000FF) ^ b; - _register = (_register >> 8) ^ crc32Table[temp]; - } - } - _TotalBytesRead += count; - } - - - /// - /// Process one byte in the CRC. - /// - /// the byte to include into the CRC . - public void UpdateCRC(byte b) - { - if (this.reverseBits) - { - UInt32 temp = (_register >> 24) ^ b; - _register = (_register << 8) ^ crc32Table[temp]; - } - else - { - UInt32 temp = (_register & 0x000000FF) ^ b; - _register = (_register >> 8) ^ crc32Table[temp]; - } - } - - /// - /// Process a run of N identical bytes into the CRC. - /// - /// - /// - /// This method serves as an optimization for updating the CRC when a - /// run of identical bytes is found. Rather than passing in a buffer of - /// length n, containing all identical bytes b, this method accepts the - /// byte value and the length of the (virtual) buffer - the length of - /// the run. - /// - /// - /// the byte to include into the CRC. - /// the number of times that byte should be repeated. - public void UpdateCRC(byte b, int n) - { - while (n-- > 0) - { - if (this.reverseBits) - { - uint temp = (_register >> 24) ^ b; - _register = (_register << 8) ^ crc32Table[(temp >= 0) - ? temp - : (temp + 256)]; - } - else - { - UInt32 temp = (_register & 0x000000FF) ^ b; - _register = (_register >> 8) ^ crc32Table[(temp >= 0) - ? temp - : (temp + 256)]; - - } - } - } - - - - private static uint ReverseBits(uint data) - { - unchecked - { - uint ret = data; - ret = (ret & 0x55555555) << 1 | (ret >> 1) & 0x55555555; - ret = (ret & 0x33333333) << 2 | (ret >> 2) & 0x33333333; - ret = (ret & 0x0F0F0F0F) << 4 | (ret >> 4) & 0x0F0F0F0F; - ret = (ret << 24) | ((ret & 0xFF00) << 8) | ((ret >> 8) & 0xFF00) | (ret >> 24); - return ret; - } - } - - private static byte ReverseBits(byte data) - { - unchecked - { - uint u = (uint)data * 0x00020202; - uint m = 0x01044010; - uint s = u & m; - uint t = (u << 2) & (m << 1); - return (byte)((0x01001001 * (s + t)) >> 24); - } - } - - - - private void GenerateLookupTable() - { - crc32Table = new UInt32[256]; - unchecked - { - UInt32 dwCrc; - byte i = 0; - do - { - dwCrc = i; - for (byte j = 8; j > 0; j--) - { - if ((dwCrc & 1) == 1) - { - dwCrc = (dwCrc >> 1) ^ dwPolynomial; - } - else - { - dwCrc >>= 1; - } - } - if (reverseBits) - { - crc32Table[ReverseBits(i)] = ReverseBits(dwCrc); - } - else - { - crc32Table[i] = dwCrc; - } - i++; - } while (i!=0); - } - -#if VERBOSE - Console.WriteLine(); - Console.WriteLine("private static readonly UInt32[] crc32Table = {"); - for (int i = 0; i < crc32Table.Length; i+=4) - { - Console.Write(" "); - for (int j=0; j < 4; j++) - { - Console.Write(" 0x{0:X8}U,", crc32Table[i+j]); - } - Console.WriteLine(); - } - Console.WriteLine("};"); - Console.WriteLine(); -#endif - } - - - private uint gf2_matrix_times(uint[] matrix, uint vec) - { - uint sum = 0; - int i=0; - while (vec != 0) - { - if ((vec & 0x01)== 0x01) - sum ^= matrix[i]; - vec >>= 1; - i++; - } - return sum; - } - - private void gf2_matrix_square(uint[] square, uint[] mat) - { - for (int i = 0; i < 32; i++) - square[i] = gf2_matrix_times(mat, mat[i]); - } - - - - /// - /// Combines the given CRC32 value with the current running total. - /// - /// - /// This is useful when using a divide-and-conquer approach to - /// calculating a CRC. Multiple threads can each calculate a - /// CRC32 on a segment of the data, and then combine the - /// individual CRC32 values at the end. - /// - /// the crc value to be combined with this one - /// the length of data the CRC value was calculated on - public void Combine(int crc, int length) - { - uint[] even = new uint[32]; // even-power-of-two zeros operator - uint[] odd = new uint[32]; // odd-power-of-two zeros operator - - if (length == 0) - return; - - uint crc1= ~_register; - uint crc2= (uint) crc; - - // put operator for one zero bit in odd - odd[0] = this.dwPolynomial; // the CRC-32 polynomial - uint row = 1; - for (int i = 1; i < 32; i++) - { - odd[i] = row; - row <<= 1; - } - - // put operator for two zero bits in even - gf2_matrix_square(even, odd); - - // put operator for four zero bits in odd - gf2_matrix_square(odd, even); - - uint len2 = (uint) length; - - // apply len2 zeros to crc1 (first square will put the operator for one - // zero byte, eight zero bits, in even) - do { - // apply zeros operator for this bit of len2 - gf2_matrix_square(even, odd); - - if ((len2 & 1)== 1) - crc1 = gf2_matrix_times(even, crc1); - len2 >>= 1; - - if (len2 == 0) - break; - - // another iteration of the loop with odd and even swapped - gf2_matrix_square(odd, even); - if ((len2 & 1)==1) - crc1 = gf2_matrix_times(odd, crc1); - len2 >>= 1; - - - } while (len2 != 0); - - crc1 ^= crc2; - - _register= ~crc1; - - //return (int) crc1; - return; - } - - - /// - /// Create an instance of the CRC32 class using the default settings: no - /// bit reversal, and a polynomial of 0xEDB88320. - /// - public CRC32() : this(false) - { - } - - /// - /// Create an instance of the CRC32 class, specifying whether to reverse - /// data bits or not. - /// - /// - /// specify true if the instance should reverse data bits. - /// - /// - /// - /// In the CRC-32 used by BZip2, the bits are reversed. Therefore if you - /// want a CRC32 with compatibility with BZip2, you should pass true - /// here. In the CRC-32 used by GZIP and PKZIP, the bits are not - /// reversed; Therefore if you want a CRC32 with compatibility with - /// those, you should pass false. - /// - /// - public CRC32(bool reverseBits) : - this( unchecked((int)0xEDB88320), reverseBits) - { - } - - - /// - /// Create an instance of the CRC32 class, specifying the polynomial and - /// whether to reverse data bits or not. - /// - /// - /// The polynomial to use for the CRC, expressed in the reversed (LSB) - /// format: the highest ordered bit in the polynomial value is the - /// coefficient of the 0th power; the second-highest order bit is the - /// coefficient of the 1 power, and so on. Expressed this way, the - /// polynomial for the CRC-32C used in IEEE 802.3, is 0xEDB88320. - /// - /// - /// specify true if the instance should reverse data bits. - /// - /// - /// - /// - /// In the CRC-32 used by BZip2, the bits are reversed. Therefore if you - /// want a CRC32 with compatibility with BZip2, you should pass true - /// here for the reverseBits parameter. In the CRC-32 used by - /// GZIP and PKZIP, the bits are not reversed; Therefore if you want a - /// CRC32 with compatibility with those, you should pass false for the - /// reverseBits parameter. - /// - /// - public CRC32(int polynomial, bool reverseBits) - { - this.reverseBits = reverseBits; - this.dwPolynomial = (uint) polynomial; - this.GenerateLookupTable(); - } - - /// - /// Reset the CRC-32 class - clear the CRC "remainder register." - /// - /// - /// - /// Use this when employing a single instance of this class to compute - /// multiple, distinct CRCs on multiple, distinct data blocks. - /// - /// - public void Reset() - { - _register = 0xFFFFFFFFU; - } - - // private member vars - private UInt32 dwPolynomial; - private Int64 _TotalBytesRead; - private bool reverseBits; - private UInt32[] crc32Table; - private const int BUFFER_SIZE = 8192; - private UInt32 _register = 0xFFFFFFFFU; - } - - - /// - /// A Stream that calculates a CRC32 (a checksum) on all bytes read, - /// or on all bytes written. - /// - /// - /// - /// - /// This class can be used to verify the CRC of a ZipEntry when - /// reading from a stream, or to calculate a CRC when writing to a - /// stream. The stream should be used to either read, or write, but - /// not both. If you intermix reads and writes, the results are not - /// defined. - /// - /// - /// - /// This class is intended primarily for use internally by the - /// DotNetZip library. - /// - /// - public class CrcCalculatorStream : System.IO.Stream, System.IDisposable - { - private static readonly Int64 UnsetLengthLimit = -99; - - internal System.IO.Stream _innerStream; - private CRC32 _Crc32; - private Int64 _lengthLimit = -99; - private bool _leaveOpen; - - /// - /// The default constructor. - /// - /// - /// - /// Instances returned from this constructor will leave the underlying - /// stream open upon Close(). The stream uses the default CRC32 - /// algorithm, which implies a polynomial of 0xEDB88320. - /// - /// - /// The underlying stream - public CrcCalculatorStream(System.IO.Stream stream) - : this(true, CrcCalculatorStream.UnsetLengthLimit, stream, null) - { - } - - /// - /// The constructor allows the caller to specify how to handle the - /// underlying stream at close. - /// - /// - /// - /// The stream uses the default CRC32 algorithm, which implies a - /// polynomial of 0xEDB88320. - /// - /// - /// The underlying stream - /// true to leave the underlying stream - /// open upon close of the CrcCalculatorStream; false otherwise. - public CrcCalculatorStream(System.IO.Stream stream, bool leaveOpen) - : this(leaveOpen, CrcCalculatorStream.UnsetLengthLimit, stream, null) - { - } - - /// - /// A constructor allowing the specification of the length of the stream - /// to read. - /// - /// - /// - /// The stream uses the default CRC32 algorithm, which implies a - /// polynomial of 0xEDB88320. - /// - /// - /// Instances returned from this constructor will leave the underlying - /// stream open upon Close(). - /// - /// - /// The underlying stream - /// The length of the stream to slurp - public CrcCalculatorStream(System.IO.Stream stream, Int64 length) - : this(true, length, stream, null) - { - if (length < 0) - throw new ArgumentException("length"); - } - - /// - /// A constructor allowing the specification of the length of the stream - /// to read, as well as whether to keep the underlying stream open upon - /// Close(). - /// - /// - /// - /// The stream uses the default CRC32 algorithm, which implies a - /// polynomial of 0xEDB88320. - /// - /// - /// The underlying stream - /// The length of the stream to slurp - /// true to leave the underlying stream - /// open upon close of the CrcCalculatorStream; false otherwise. - public CrcCalculatorStream(System.IO.Stream stream, Int64 length, bool leaveOpen) - : this(leaveOpen, length, stream, null) - { - if (length < 0) - throw new ArgumentException("length"); - } - - /// - /// A constructor allowing the specification of the length of the stream - /// to read, as well as whether to keep the underlying stream open upon - /// Close(), and the CRC32 instance to use. - /// - /// - /// - /// The stream uses the specified CRC32 instance, which allows the - /// application to specify how the CRC gets calculated. - /// - /// - /// The underlying stream - /// The length of the stream to slurp - /// true to leave the underlying stream - /// open upon close of the CrcCalculatorStream; false otherwise. - /// the CRC32 instance to use to calculate the CRC32 - public CrcCalculatorStream(System.IO.Stream stream, Int64 length, bool leaveOpen, - CRC32 crc32) - : this(leaveOpen, length, stream, crc32) - { - if (length < 0) - throw new ArgumentException("length"); - } - - - // This ctor is private - no validation is done here. This is to allow the use - // of a (specific) negative value for the _lengthLimit, to indicate that there - // is no length set. So we validate the length limit in those ctors that use an - // explicit param, otherwise we don't validate, because it could be our special - // value. - private CrcCalculatorStream - (bool leaveOpen, Int64 length, System.IO.Stream stream, CRC32 crc32) - : base() - { - _innerStream = stream; - _Crc32 = crc32 ?? new CRC32(); - _lengthLimit = length; - _leaveOpen = leaveOpen; - } - - - /// - /// Gets the total number of bytes run through the CRC32 calculator. - /// - /// - /// - /// This is either the total number of bytes read, or the total number of - /// bytes written, depending on the direction of this stream. - /// - public Int64 TotalBytesSlurped - { - get { return _Crc32.TotalBytesRead; } - } - - /// - /// Provides the current CRC for all blocks slurped in. - /// - /// - /// - /// The running total of the CRC is kept as data is written or read - /// through the stream. read this property after all reads or writes to - /// get an accurate CRC for the entire stream. - /// - /// - public Int32 Crc - { - get { return _Crc32.Crc32Result; } - } - - /// - /// Indicates whether the underlying stream will be left open when the - /// CrcCalculatorStream is Closed. - /// - /// - /// - /// Set this at any point before calling . - /// - /// - public bool LeaveOpen - { - get { return _leaveOpen; } - set { _leaveOpen = value; } - } - - /// - /// Read from the stream - /// - /// the buffer to read - /// the offset at which to start - /// the number of bytes to read - /// the number of bytes actually read - public override int Read(byte[] buffer, int offset, int count) - { - int bytesToRead = count; - - // Need to limit the # of bytes returned, if the stream is intended to have - // a definite length. This is especially useful when returning a stream for - // the uncompressed data directly to the application. The app won't - // necessarily read only the UncompressedSize number of bytes. For example - // wrapping the stream returned from OpenReader() into a StreadReader() and - // calling ReadToEnd() on it, We can "over-read" the zip data and get a - // corrupt string. The length limits that, prevents that problem. - - if (_lengthLimit != CrcCalculatorStream.UnsetLengthLimit) - { - if (_Crc32.TotalBytesRead >= _lengthLimit) return 0; // EOF - Int64 bytesRemaining = _lengthLimit - _Crc32.TotalBytesRead; - if (bytesRemaining < count) bytesToRead = (int)bytesRemaining; - } - int n = _innerStream.Read(buffer, offset, bytesToRead); - if (n > 0) _Crc32.SlurpBlock(buffer, offset, n); - return n; - } - - /// - /// Write to the stream. - /// - /// the buffer from which to write - /// the offset at which to start writing - /// the number of bytes to write - public override void Write(byte[] buffer, int offset, int count) - { - if (count > 0) _Crc32.SlurpBlock(buffer, offset, count); - _innerStream.Write(buffer, offset, count); - } - - /// - /// Indicates whether the stream supports reading. - /// - public override bool CanRead - { - get { return _innerStream.CanRead; } - } - - /// - /// Indicates whether the stream supports seeking. - /// - /// - /// - /// Always returns false. - /// - /// - public override bool CanSeek - { - get { return false; } - } - - /// - /// Indicates whether the stream supports writing. - /// - public override bool CanWrite - { - get { return _innerStream.CanWrite; } - } - - /// - /// Flush the stream. - /// - public override void Flush() - { - _innerStream.Flush(); - } - - /// - /// Returns the length of the underlying stream. - /// - public override long Length - { - get - { - if (_lengthLimit == CrcCalculatorStream.UnsetLengthLimit) - return _innerStream.Length; - else return _lengthLimit; - } - } - - /// - /// The getter for this property returns the total bytes read. - /// If you use the setter, it will throw - /// . - /// - public override long Position - { - get { return _Crc32.TotalBytesRead; } - set { throw new NotSupportedException(); } - } - - /// - /// Seeking is not supported on this stream. This method always throws - /// - /// - /// N/A - /// N/A - /// N/A - public override long Seek(long offset, System.IO.SeekOrigin origin) - { - throw new NotSupportedException(); - } - - /// - /// This method always throws - /// - /// - /// N/A - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - - void IDisposable.Dispose() - { - Close(); - } - - /// - /// Closes the stream. - /// - public override void Close() - { - base.Close(); - if (!_leaveOpen) - _innerStream.Close(); - } - - } - -} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/Compression/Deflate.cs b/MinecraftClient/Protocol/Handlers/Compression/Deflate.cs deleted file mode 100644 index 96722507..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Deflate.cs +++ /dev/null @@ -1,1879 +0,0 @@ -// Deflate.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation. -// 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-August-03 19:52:15> -// -// ------------------------------------------------------------------ -// -// This module defines logic for handling the Deflate or compression. -// -// This code is based on multiple sources: -// - the original zlib v1.2.3 source, which is Copyright (C) 1995-2005 Jean-loup Gailly. -// - the original jzlib, which is Copyright (c) 2000-2003 ymnk, JCraft,Inc. -// -// However, this code is significantly different from both. -// The object model is not the same, and many of the behaviors are different. -// -// In keeping with the license for these other works, the copyrights for -// jzlib and zlib are here. -// -// ----------------------------------------------------------------------- -// Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in -// the documentation and/or other materials provided with the distribution. -// -// 3. The names of the authors may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -// INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// ----------------------------------------------------------------------- -// -// This program is based on zlib-1.1.3; credit to authors -// Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) -// and contributors of zlib. -// -// ----------------------------------------------------------------------- - - -using System; - -namespace Ionic.Zlib -{ - - internal enum BlockState - { - NeedMore = 0, // block not completed, need more input or more output - BlockDone, // block flush performed - FinishStarted, // finish started, need only more output at next deflate - FinishDone // finish done, accept no more input or output - } - - internal enum DeflateFlavor - { - Store, - Fast, - Slow - } - - internal sealed class DeflateManager - { - private static readonly int MEM_LEVEL_MAX = 9; - private static readonly int MEM_LEVEL_DEFAULT = 8; - - internal delegate BlockState CompressFunc(FlushType flush); - - internal class Config - { - // Use a faster search when the previous match is longer than this - internal int GoodLength; // reduce lazy search above this match length - - // Attempt to find a better match only when the current match is - // strictly smaller than this value. This mechanism is used only for - // compression levels >= 4. For levels 1,2,3: MaxLazy is actually - // MaxInsertLength. (See DeflateFast) - - internal int MaxLazy; // do not perform lazy search above this match length - - internal int NiceLength; // quit search above this match length - - // To speed up deflation, hash chains are never searched beyond this - // length. A higher limit improves compression ratio but degrades the speed. - - internal int MaxChainLength; - - internal DeflateFlavor Flavor; - - private Config(int goodLength, int maxLazy, int niceLength, int maxChainLength, DeflateFlavor flavor) - { - this.GoodLength = goodLength; - this.MaxLazy = maxLazy; - this.NiceLength = niceLength; - this.MaxChainLength = maxChainLength; - this.Flavor = flavor; - } - - public static Config Lookup(CompressionLevel level) - { - return Table[(int)level]; - } - - - static Config() - { - Table = new Config[] { - new Config(0, 0, 0, 0, DeflateFlavor.Store), - new Config(4, 4, 8, 4, DeflateFlavor.Fast), - new Config(4, 5, 16, 8, DeflateFlavor.Fast), - new Config(4, 6, 32, 32, DeflateFlavor.Fast), - - new Config(4, 4, 16, 16, DeflateFlavor.Slow), - new Config(8, 16, 32, 32, DeflateFlavor.Slow), - new Config(8, 16, 128, 128, DeflateFlavor.Slow), - new Config(8, 32, 128, 256, DeflateFlavor.Slow), - new Config(32, 128, 258, 1024, DeflateFlavor.Slow), - new Config(32, 258, 258, 4096, DeflateFlavor.Slow), - }; - } - - private static readonly Config[] Table; - } - - - private CompressFunc DeflateFunction; - - private static readonly System.String[] _ErrorMessage = new System.String[] - { - "need dictionary", - "stream end", - "", - "file error", - "stream error", - "data error", - "insufficient memory", - "buffer error", - "incompatible version", - "" - }; - - // preset dictionary flag in zlib header - private static readonly int PRESET_DICT = 0x20; - - private static readonly int INIT_STATE = 42; - private static readonly int BUSY_STATE = 113; - private static readonly int FINISH_STATE = 666; - - // The deflate compression method - private static readonly int Z_DEFLATED = 8; - - private static readonly int STORED_BLOCK = 0; - private static readonly int STATIC_TREES = 1; - private static readonly int DYN_TREES = 2; - - // The three kinds of block type - private static readonly int Z_BINARY = 0; - private static readonly int Z_ASCII = 1; - private static readonly int Z_UNKNOWN = 2; - - private static readonly int Buf_size = 8 * 2; - - private static readonly int MIN_MATCH = 3; - private static readonly int MAX_MATCH = 258; - - private static readonly int MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1); - - private static readonly int HEAP_SIZE = (2 * InternalConstants.L_CODES + 1); - - private static readonly int END_BLOCK = 256; - - internal ZlibCodec _codec; // the zlib encoder/decoder - internal int status; // as the name implies - internal byte[] pending; // output still pending - waiting to be compressed - internal int nextPending; // index of next pending byte to output to the stream - internal int pendingCount; // number of bytes in the pending buffer - - internal sbyte data_type; // UNKNOWN, BINARY or ASCII - internal int last_flush; // value of flush param for previous deflate call - - internal int w_size; // LZ77 window size (32K by default) - internal int w_bits; // log2(w_size) (8..16) - internal int w_mask; // w_size - 1 - - //internal byte[] dictionary; - internal byte[] window; - - // Sliding window. Input bytes are read into the second half of the window, - // and move to the first half later to keep a dictionary of at least wSize - // bytes. With this organization, matches are limited to a distance of - // wSize-MAX_MATCH bytes, but this ensures that IO is always - // performed with a length multiple of the block size. - // - // To do: use the user input buffer as sliding window. - - internal int window_size; - // Actual size of window: 2*wSize, except when the user input buffer - // is directly used as sliding window. - - internal short[] prev; - // Link to older string with same hash index. To limit the size of this - // array to 64K, this link is maintained only for the last 32K strings. - // An index in this array is thus a window index modulo 32K. - - internal short[] head; // Heads of the hash chains or NIL. - - internal int ins_h; // hash index of string to be inserted - internal int hash_size; // number of elements in hash table - internal int hash_bits; // log2(hash_size) - internal int hash_mask; // hash_size-1 - - // Number of bits by which ins_h must be shifted at each input - // step. It must be such that after MIN_MATCH steps, the oldest - // byte no longer takes part in the hash key, that is: - // hash_shift * MIN_MATCH >= hash_bits - internal int hash_shift; - - // Window position at the beginning of the current output block. Gets - // negative when the window is moved backwards. - - internal int block_start; - - Config config; - internal int match_length; // length of best match - internal int prev_match; // previous match - internal int match_available; // set if previous match exists - internal int strstart; // start of string to insert into.....???? - internal int match_start; // start of matching string - internal int lookahead; // number of valid bytes ahead in window - - // Length of the best match at previous step. Matches not greater than this - // are discarded. This is used in the lazy match evaluation. - internal int prev_length; - - // Insert new strings in the hash table only if the match length is not - // greater than this length. This saves time but degrades compression. - // max_insert_length is used only for compression levels <= 3. - - internal CompressionLevel compressionLevel; // compression level (1..9) - internal CompressionStrategy compressionStrategy; // favor or force Huffman coding - - - internal short[] dyn_ltree; // literal and length tree - internal short[] dyn_dtree; // distance tree - internal short[] bl_tree; // Huffman tree for bit lengths - - internal Tree treeLiterals = new Tree(); // desc for literal tree - internal Tree treeDistances = new Tree(); // desc for distance tree - internal Tree treeBitLengths = new Tree(); // desc for bit length tree - - // number of codes at each bit length for an optimal tree - internal short[] bl_count = new short[InternalConstants.MAX_BITS + 1]; - - // heap used to build the Huffman trees - internal int[] heap = new int[2 * InternalConstants.L_CODES + 1]; - - internal int heap_len; // number of elements in the heap - internal int heap_max; // element of largest frequency - - // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. - // The same heap array is used to build all trees. - - // Depth of each subtree used as tie breaker for trees of equal frequency - internal sbyte[] depth = new sbyte[2 * InternalConstants.L_CODES + 1]; - - internal int _lengthOffset; // index for literals or lengths - - - // Size of match buffer for literals/lengths. There are 4 reasons for - // limiting lit_bufsize to 64K: - // - frequencies can be kept in 16 bit counters - // - if compression is not successful for the first block, all input - // data is still in the window so we can still emit a stored block even - // when input comes from standard input. (This can also be done for - // all blocks if lit_bufsize is not greater than 32K.) - // - if compression is not successful for a file smaller than 64K, we can - // even emit a stored file instead of a stored block (saving 5 bytes). - // This is applicable only for zip (not gzip or zlib). - // - creating new Huffman trees less frequently may not provide fast - // adaptation to changes in the input data statistics. (Take for - // example a binary file with poorly compressible code followed by - // a highly compressible string table.) Smaller buffer sizes give - // fast adaptation but have of course the overhead of transmitting - // trees more frequently. - - internal int lit_bufsize; - - internal int last_lit; // running index in l_buf - - // Buffer for distances. To simplify the code, d_buf and l_buf have - // the same number of elements. To use different lengths, an extra flag - // array would be necessary. - - internal int _distanceOffset; // index into pending; points to distance data?? - - internal int opt_len; // bit length of current block with optimal trees - internal int static_len; // bit length of current block with static trees - internal int matches; // number of string matches in current block - internal int last_eob_len; // bit length of EOB code for last block - - // Output buffer. bits are inserted starting at the bottom (least - // significant bits). - internal short bi_buf; - - // Number of valid bits in bi_buf. All bits above the last valid bit - // are always zero. - internal int bi_valid; - - - internal DeflateManager() - { - dyn_ltree = new short[HEAP_SIZE * 2]; - dyn_dtree = new short[(2 * InternalConstants.D_CODES + 1) * 2]; // distance tree - bl_tree = new short[(2 * InternalConstants.BL_CODES + 1) * 2]; // Huffman tree for bit lengths - } - - - // lm_init - private void _InitializeLazyMatch() - { - window_size = 2 * w_size; - - // clear the hash - workitem 9063 - Array.Clear(head, 0, hash_size); - //for (int i = 0; i < hash_size; i++) head[i] = 0; - - config = Config.Lookup(compressionLevel); - SetDeflater(); - - strstart = 0; - block_start = 0; - lookahead = 0; - match_length = prev_length = MIN_MATCH - 1; - match_available = 0; - ins_h = 0; - } - - // Initialize the tree data structures for a new zlib stream. - private void _InitializeTreeData() - { - treeLiterals.dyn_tree = dyn_ltree; - treeLiterals.staticTree = StaticTree.Literals; - - treeDistances.dyn_tree = dyn_dtree; - treeDistances.staticTree = StaticTree.Distances; - - treeBitLengths.dyn_tree = bl_tree; - treeBitLengths.staticTree = StaticTree.BitLengths; - - bi_buf = 0; - bi_valid = 0; - last_eob_len = 8; // enough lookahead for inflate - - // Initialize the first block of the first file: - _InitializeBlocks(); - } - - internal void _InitializeBlocks() - { - // Initialize the trees. - for (int i = 0; i < InternalConstants.L_CODES; i++) - dyn_ltree[i * 2] = 0; - for (int i = 0; i < InternalConstants.D_CODES; i++) - dyn_dtree[i * 2] = 0; - for (int i = 0; i < InternalConstants.BL_CODES; i++) - bl_tree[i * 2] = 0; - - dyn_ltree[END_BLOCK * 2] = 1; - opt_len = static_len = 0; - last_lit = matches = 0; - } - - // Restore the heap property by moving down the tree starting at node k, - // exchanging a node with the smallest of its two sons if necessary, stopping - // when the heap property is re-established (each father smaller than its - // two sons). - internal void pqdownheap(short[] tree, int k) - { - int v = heap[k]; - int j = k << 1; // left son of k - while (j <= heap_len) - { - // Set j to the smallest of the two sons: - if (j < heap_len && _IsSmaller(tree, heap[j + 1], heap[j], depth)) - { - j++; - } - // Exit if v is smaller than both sons - if (_IsSmaller(tree, v, heap[j], depth)) - break; - - // Exchange v with the smallest son - heap[k] = heap[j]; k = j; - // And continue down the tree, setting j to the left son of k - j <<= 1; - } - heap[k] = v; - } - - internal static bool _IsSmaller(short[] tree, int n, int m, sbyte[] depth) - { - short tn2 = tree[n * 2]; - short tm2 = tree[m * 2]; - return (tn2 < tm2 || (tn2 == tm2 && depth[n] <= depth[m])); - } - - - // Scan a literal or distance tree to determine the frequencies of the codes - // in the bit length tree. - internal void scan_tree(short[] tree, int max_code) - { - int n; // iterates over all tree elements - int prevlen = -1; // last emitted length - int curlen; // length of current code - int nextlen = (int)tree[0 * 2 + 1]; // length of next code - int count = 0; // repeat count of the current code - int max_count = 7; // max repeat count - int min_count = 4; // min repeat count - - if (nextlen == 0) - { - max_count = 138; min_count = 3; - } - tree[(max_code + 1) * 2 + 1] = (short)0x7fff; // guard //?? - - for (n = 0; n <= max_code; n++) - { - curlen = nextlen; nextlen = (int)tree[(n + 1) * 2 + 1]; - if (++count < max_count && curlen == nextlen) - { - continue; - } - else if (count < min_count) - { - bl_tree[curlen * 2] = (short)(bl_tree[curlen * 2] + count); - } - else if (curlen != 0) - { - if (curlen != prevlen) - bl_tree[curlen * 2]++; - bl_tree[InternalConstants.REP_3_6 * 2]++; - } - else if (count <= 10) - { - bl_tree[InternalConstants.REPZ_3_10 * 2]++; - } - else - { - bl_tree[InternalConstants.REPZ_11_138 * 2]++; - } - count = 0; prevlen = curlen; - if (nextlen == 0) - { - max_count = 138; min_count = 3; - } - else if (curlen == nextlen) - { - max_count = 6; min_count = 3; - } - else - { - max_count = 7; min_count = 4; - } - } - } - - // Construct the Huffman tree for the bit lengths and return the index in - // bl_order of the last bit length code to send. - internal int build_bl_tree() - { - int max_blindex; // index of last bit length code of non zero freq - - // Determine the bit length frequencies for literal and distance trees - scan_tree(dyn_ltree, treeLiterals.max_code); - scan_tree(dyn_dtree, treeDistances.max_code); - - // Build the bit length tree: - treeBitLengths.build_tree(this); - // opt_len now includes the length of the tree representations, except - // the lengths of the bit lengths codes and the 5+5+4 bits for the counts. - - // Determine the number of bit length codes to send. The pkzip format - // requires that at least 4 bit length codes be sent. (appnote.txt says - // 3 but the actual value used is 4.) - for (max_blindex = InternalConstants.BL_CODES - 1; max_blindex >= 3; max_blindex--) - { - if (bl_tree[Tree.bl_order[max_blindex] * 2 + 1] != 0) - break; - } - // Update opt_len to include the bit length tree and counts - opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4; - - return max_blindex; - } - - - // Send the header for a block using dynamic Huffman trees: the counts, the - // lengths of the bit length codes, the literal tree and the distance tree. - // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. - internal void send_all_trees(int lcodes, int dcodes, int blcodes) - { - int rank; // index in bl_order - - send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt - send_bits(dcodes - 1, 5); - send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt - for (rank = 0; rank < blcodes; rank++) - { - send_bits(bl_tree[Tree.bl_order[rank] * 2 + 1], 3); - } - send_tree(dyn_ltree, lcodes - 1); // literal tree - send_tree(dyn_dtree, dcodes - 1); // distance tree - } - - // Send a literal or distance tree in compressed form, using the codes in - // bl_tree. - internal void send_tree(short[] tree, int max_code) - { - int n; // iterates over all tree elements - int prevlen = -1; // last emitted length - int curlen; // length of current code - int nextlen = tree[0 * 2 + 1]; // length of next code - int count = 0; // repeat count of the current code - int max_count = 7; // max repeat count - int min_count = 4; // min repeat count - - if (nextlen == 0) - { - max_count = 138; min_count = 3; - } - - for (n = 0; n <= max_code; n++) - { - curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1]; - if (++count < max_count && curlen == nextlen) - { - continue; - } - else if (count < min_count) - { - do - { - send_code(curlen, bl_tree); - } - while (--count != 0); - } - else if (curlen != 0) - { - if (curlen != prevlen) - { - send_code(curlen, bl_tree); count--; - } - send_code(InternalConstants.REP_3_6, bl_tree); - send_bits(count - 3, 2); - } - else if (count <= 10) - { - send_code(InternalConstants.REPZ_3_10, bl_tree); - send_bits(count - 3, 3); - } - else - { - send_code(InternalConstants.REPZ_11_138, bl_tree); - send_bits(count - 11, 7); - } - count = 0; prevlen = curlen; - if (nextlen == 0) - { - max_count = 138; min_count = 3; - } - else if (curlen == nextlen) - { - max_count = 6; min_count = 3; - } - else - { - max_count = 7; min_count = 4; - } - } - } - - // Output a block of bytes on the stream. - // IN assertion: there is enough room in pending_buf. - private void put_bytes(byte[] p, int start, int len) - { - Array.Copy(p, start, pending, pendingCount, len); - pendingCount += len; - } - -#if NOTNEEDED - private void put_byte(byte c) - { - pending[pendingCount++] = c; - } - internal void put_short(int b) - { - unchecked - { - pending[pendingCount++] = (byte)b; - pending[pendingCount++] = (byte)(b >> 8); - } - } - internal void putShortMSB(int b) - { - unchecked - { - pending[pendingCount++] = (byte)(b >> 8); - pending[pendingCount++] = (byte)b; - } - } -#endif - - internal void send_code(int c, short[] tree) - { - int c2 = c * 2; - send_bits((tree[c2] & 0xffff), (tree[c2 + 1] & 0xffff)); - } - - internal void send_bits(int value, int length) - { - int len = length; - unchecked - { - if (bi_valid > (int)Buf_size - len) - { - //int val = value; - // bi_buf |= (val << bi_valid); - - bi_buf |= (short)((value << bi_valid) & 0xffff); - //put_short(bi_buf); - pending[pendingCount++] = (byte)bi_buf; - pending[pendingCount++] = (byte)(bi_buf >> 8); - - - bi_buf = (short)((uint)value >> (Buf_size - bi_valid)); - bi_valid += len - Buf_size; - } - else - { - // bi_buf |= (value) << bi_valid; - bi_buf |= (short)((value << bi_valid) & 0xffff); - bi_valid += len; - } - } - } - - // Send one empty static block to give enough lookahead for inflate. - // This takes 10 bits, of which 7 may remain in the bit buffer. - // The current inflate code requires 9 bits of lookahead. If the - // last two codes for the previous block (real code plus EOB) were coded - // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode - // the last real code. In this case we send two empty static blocks instead - // of one. (There are no problems if the previous block is stored or fixed.) - // To simplify the code, we assume the worst case of last real code encoded - // on one bit only. - internal void _tr_align() - { - send_bits(STATIC_TREES << 1, 3); - send_code(END_BLOCK, StaticTree.lengthAndLiteralsTreeCodes); - - bi_flush(); - - // Of the 10 bits for the empty block, we have already sent - // (10 - bi_valid) bits. The lookahead for the last real code (before - // the EOB of the previous block) was thus at least one plus the length - // of the EOB plus what we have just sent of the empty static block. - if (1 + last_eob_len + 10 - bi_valid < 9) - { - send_bits(STATIC_TREES << 1, 3); - send_code(END_BLOCK, StaticTree.lengthAndLiteralsTreeCodes); - bi_flush(); - } - last_eob_len = 7; - } - - - // Save the match info and tally the frequency counts. Return true if - // the current block must be flushed. - internal bool _tr_tally(int dist, int lc) - { - pending[_distanceOffset + last_lit * 2] = unchecked((byte) ( (uint)dist >> 8 ) ); - pending[_distanceOffset + last_lit * 2 + 1] = unchecked((byte)dist); - pending[_lengthOffset + last_lit] = unchecked((byte)lc); - last_lit++; - - if (dist == 0) - { - // lc is the unmatched char - dyn_ltree[lc * 2]++; - } - else - { - matches++; - // Here, lc is the match length - MIN_MATCH - dist--; // dist = match distance - 1 - dyn_ltree[(Tree.LengthCode[lc] + InternalConstants.LITERALS + 1) * 2]++; - dyn_dtree[Tree.DistanceCode(dist) * 2]++; - } - - if ((last_lit & 0x1fff) == 0 && (int)compressionLevel > 2) - { - // Compute an upper bound for the compressed length - int out_length = last_lit << 3; - int in_length = strstart - block_start; - int dcode; - for (dcode = 0; dcode < InternalConstants.D_CODES; dcode++) - { - out_length = (int)(out_length + (int)dyn_dtree[dcode * 2] * (5L + Tree.ExtraDistanceBits[dcode])); - } - out_length >>= 3; - if ((matches < (last_lit / 2)) && out_length < in_length / 2) - return true; - } - - return (last_lit == lit_bufsize - 1) || (last_lit == lit_bufsize); - // dinoch - wraparound? - // We avoid equality with lit_bufsize because of wraparound at 64K - // on 16 bit machines and because stored blocks are restricted to - // 64K-1 bytes. - } - - - - // Send the block data compressed using the given Huffman trees - internal void send_compressed_block(short[] ltree, short[] dtree) - { - int distance; // distance of matched string - int lc; // match length or unmatched char (if dist == 0) - int lx = 0; // running index in l_buf - int code; // the code to send - int extra; // number of extra bits to send - - if (last_lit != 0) - { - do - { - int ix = _distanceOffset + lx * 2; - distance = ((pending[ix] << 8) & 0xff00) | - (pending[ix + 1] & 0xff); - lc = (pending[_lengthOffset + lx]) & 0xff; - lx++; - - if (distance == 0) - { - send_code(lc, ltree); // send a literal byte - } - else - { - // literal or match pair - // Here, lc is the match length - MIN_MATCH - code = Tree.LengthCode[lc]; - - // send the length code - send_code(code + InternalConstants.LITERALS + 1, ltree); - extra = Tree.ExtraLengthBits[code]; - if (extra != 0) - { - // send the extra length bits - lc -= Tree.LengthBase[code]; - send_bits(lc, extra); - } - distance--; // dist is now the match distance - 1 - code = Tree.DistanceCode(distance); - - // send the distance code - send_code(code, dtree); - - extra = Tree.ExtraDistanceBits[code]; - if (extra != 0) - { - // send the extra distance bits - distance -= Tree.DistanceBase[code]; - send_bits(distance, extra); - } - } - - // Check that the overlay between pending and d_buf+l_buf is ok: - } - while (lx < last_lit); - } - - send_code(END_BLOCK, ltree); - last_eob_len = ltree[END_BLOCK * 2 + 1]; - } - - - - // Set the data type to ASCII or BINARY, using a crude approximation: - // binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. - // IN assertion: the fields freq of dyn_ltree are set and the total of all - // frequencies does not exceed 64K (to fit in an int on 16 bit machines). - internal void set_data_type() - { - int n = 0; - int ascii_freq = 0; - int bin_freq = 0; - while (n < 7) - { - bin_freq += dyn_ltree[n * 2]; n++; - } - while (n < 128) - { - ascii_freq += dyn_ltree[n * 2]; n++; - } - while (n < InternalConstants.LITERALS) - { - bin_freq += dyn_ltree[n * 2]; n++; - } - data_type = (sbyte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); - } - - - - // Flush the bit buffer, keeping at most 7 bits in it. - internal void bi_flush() - { - if (bi_valid == 16) - { - pending[pendingCount++] = (byte)bi_buf; - pending[pendingCount++] = (byte)(bi_buf >> 8); - bi_buf = 0; - bi_valid = 0; - } - else if (bi_valid >= 8) - { - //put_byte((byte)bi_buf); - pending[pendingCount++] = (byte)bi_buf; - bi_buf >>= 8; - bi_valid -= 8; - } - } - - // Flush the bit buffer and align the output on a byte boundary - internal void bi_windup() - { - if (bi_valid > 8) - { - pending[pendingCount++] = (byte)bi_buf; - pending[pendingCount++] = (byte)(bi_buf >> 8); - } - else if (bi_valid > 0) - { - //put_byte((byte)bi_buf); - pending[pendingCount++] = (byte)bi_buf; - } - bi_buf = 0; - bi_valid = 0; - } - - // Copy a stored block, storing first the length and its - // one's complement if requested. - internal void copy_block(int buf, int len, bool header) - { - bi_windup(); // align on byte boundary - last_eob_len = 8; // enough lookahead for inflate - - if (header) - unchecked - { - //put_short((short)len); - pending[pendingCount++] = (byte)len; - pending[pendingCount++] = (byte)(len >> 8); - //put_short((short)~len); - pending[pendingCount++] = (byte)~len; - pending[pendingCount++] = (byte)(~len >> 8); - } - - put_bytes(window, buf, len); - } - - internal void flush_block_only(bool eof) - { - _tr_flush_block(block_start >= 0 ? block_start : -1, strstart - block_start, eof); - block_start = strstart; - _codec.flush_pending(); - } - - // Copy without compression as much as possible from the input stream, return - // the current block state. - // This function does not insert new strings in the dictionary since - // uncompressible data is probably not useful. This function is used - // only for the level=0 compression option. - // NOTE: this function should be optimized to avoid extra copying from - // window to pending_buf. - internal BlockState DeflateNone(FlushType flush) - { - // Stored blocks are limited to 0xffff bytes, pending is limited - // to pending_buf_size, and each stored block has a 5 byte header: - - int max_block_size = 0xffff; - int max_start; - - if (max_block_size > pending.Length - 5) - { - max_block_size = pending.Length - 5; - } - - // Copy as much as possible from input to output: - while (true) - { - // Fill the window as much as possible: - if (lookahead <= 1) - { - _fillWindow(); - if (lookahead == 0 && flush == FlushType.None) - return BlockState.NeedMore; - if (lookahead == 0) - break; // flush the current block - } - - strstart += lookahead; - lookahead = 0; - - // Emit a stored block if pending will be full: - max_start = block_start + max_block_size; - if (strstart == 0 || strstart >= max_start) - { - // strstart == 0 is possible when wraparound on 16-bit machine - lookahead = (int)(strstart - max_start); - strstart = (int)max_start; - - flush_block_only(false); - if (_codec.AvailableBytesOut == 0) - return BlockState.NeedMore; - } - - // Flush if we may have to slide, otherwise block_start may become - // negative and the data will be gone: - if (strstart - block_start >= w_size - MIN_LOOKAHEAD) - { - flush_block_only(false); - if (_codec.AvailableBytesOut == 0) - return BlockState.NeedMore; - } - } - - flush_block_only(flush == FlushType.Finish); - if (_codec.AvailableBytesOut == 0) - return (flush == FlushType.Finish) ? BlockState.FinishStarted : BlockState.NeedMore; - - return flush == FlushType.Finish ? BlockState.FinishDone : BlockState.BlockDone; - } - - - // Send a stored block - internal void _tr_stored_block(int buf, int stored_len, bool eof) - { - send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type - copy_block(buf, stored_len, true); // with header - } - - // Determine the best encoding for the current block: dynamic trees, static - // trees or store, and output the encoded block to the zip file. - internal void _tr_flush_block(int buf, int stored_len, bool eof) - { - int opt_lenb, static_lenb; // opt_len and static_len in bytes - int max_blindex = 0; // index of last bit length code of non zero freq - - // Build the Huffman trees unless a stored block is forced - if (compressionLevel > 0) - { - // Check if the file is ascii or binary - if (data_type == Z_UNKNOWN) - set_data_type(); - - // Construct the literal and distance trees - treeLiterals.build_tree(this); - - treeDistances.build_tree(this); - - // At this point, opt_len and static_len are the total bit lengths of - // the compressed block data, excluding the tree representations. - - // Build the bit length tree for the above two trees, and get the index - // in bl_order of the last bit length code to send. - max_blindex = build_bl_tree(); - - // Determine the best encoding. Compute first the block length in bytes - opt_lenb = (opt_len + 3 + 7) >> 3; - static_lenb = (static_len + 3 + 7) >> 3; - - if (static_lenb <= opt_lenb) - opt_lenb = static_lenb; - } - else - { - opt_lenb = static_lenb = stored_len + 5; // force a stored block - } - - if (stored_len + 4 <= opt_lenb && buf != -1) - { - // 4: two words for the lengths - // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. - // Otherwise we can't have processed more than WSIZE input bytes since - // the last block flush, because compression would have been - // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to - // transform a block into a stored block. - _tr_stored_block(buf, stored_len, eof); - } - else if (static_lenb == opt_lenb) - { - send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3); - send_compressed_block(StaticTree.lengthAndLiteralsTreeCodes, StaticTree.distTreeCodes); - } - else - { - send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3); - send_all_trees(treeLiterals.max_code + 1, treeDistances.max_code + 1, max_blindex + 1); - send_compressed_block(dyn_ltree, dyn_dtree); - } - - // The above check is made mod 2^32, for files larger than 512 MB - // and uLong implemented on 32 bits. - - _InitializeBlocks(); - - if (eof) - { - bi_windup(); - } - } - - // Fill the window when the lookahead becomes insufficient. - // Updates strstart and lookahead. - // - // IN assertion: lookahead < MIN_LOOKAHEAD - // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD - // At least one byte has been read, or avail_in == 0; reads are - // performed for at least two bytes (required for the zip translate_eol - // option -- not supported here). - private void _fillWindow() - { - int n, m; - int p; - int more; // Amount of free space at the end of the window. - - do - { - more = (window_size - lookahead - strstart); - - // Deal with !@#$% 64K limit: - if (more == 0 && strstart == 0 && lookahead == 0) - { - more = w_size; - } - else if (more == -1) - { - // Very unlikely, but possible on 16 bit machine if strstart == 0 - // and lookahead == 1 (input done one byte at time) - more--; - - // If the window is almost full and there is insufficient lookahead, - // move the upper half to the lower one to make room in the upper half. - } - else if (strstart >= w_size + w_size - MIN_LOOKAHEAD) - { - Array.Copy(window, w_size, window, 0, w_size); - match_start -= w_size; - strstart -= w_size; // we now have strstart >= MAX_DIST - block_start -= w_size; - - // Slide the hash table (could be avoided with 32 bit values - // at the expense of memory usage). We slide even when level == 0 - // to keep the hash table consistent if we switch back to level > 0 - // later. (Using level 0 permanently is not an optimal usage of - // zlib, so we don't care about this pathological case.) - - n = hash_size; - p = n; - do - { - m = (head[--p] & 0xffff); - head[p] = (short)((m >= w_size) ? (m - w_size) : 0); - } - while (--n != 0); - - n = w_size; - p = n; - do - { - m = (prev[--p] & 0xffff); - prev[p] = (short)((m >= w_size) ? (m - w_size) : 0); - // If n is not on any hash chain, prev[n] is garbage but - // its value will never be used. - } - while (--n != 0); - more += w_size; - } - - if (_codec.AvailableBytesIn == 0) - return; - - // If there was no sliding: - // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && - // more == window_size - lookahead - strstart - // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) - // => more >= window_size - 2*WSIZE + 2 - // In the BIG_MEM or MMAP case (not yet supported), - // window_size == input_size + MIN_LOOKAHEAD && - // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. - // Otherwise, window_size == 2*WSIZE so more >= 2. - // If there was sliding, more >= WSIZE. So in all cases, more >= 2. - - n = _codec.read_buf(window, strstart + lookahead, more); - lookahead += n; - - // Initialize the hash value now that we have some input: - if (lookahead >= MIN_MATCH) - { - ins_h = window[strstart] & 0xff; - ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask; - } - // If the whole input has less than MIN_MATCH bytes, ins_h is garbage, - // but this is not important since only literal bytes will be emitted. - } - while (lookahead < MIN_LOOKAHEAD && _codec.AvailableBytesIn != 0); - } - - // Compress as much as possible from the input stream, return the current - // block state. - // This function does not perform lazy evaluation of matches and inserts - // new strings in the dictionary only for unmatched strings or for short - // matches. It is used only for the fast compression options. - internal BlockState DeflateFast(FlushType flush) - { - // short hash_head = 0; // head of the hash chain - int hash_head = 0; // head of the hash chain - bool bflush; // set if current block must be flushed - - while (true) - { - // Make sure that we always have enough lookahead, except - // at the end of the input file. We need MAX_MATCH bytes - // for the next match, plus MIN_MATCH bytes to insert the - // string following the next match. - if (lookahead < MIN_LOOKAHEAD) - { - _fillWindow(); - if (lookahead < MIN_LOOKAHEAD && flush == FlushType.None) - { - return BlockState.NeedMore; - } - if (lookahead == 0) - break; // flush the current block - } - - // Insert the string window[strstart .. strstart+2] in the - // dictionary, and set hash_head to the head of the hash chain: - if (lookahead >= MIN_MATCH) - { - ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask; - - // prev[strstart&w_mask]=hash_head=head[ins_h]; - hash_head = (head[ins_h] & 0xffff); - prev[strstart & w_mask] = head[ins_h]; - head[ins_h] = unchecked((short)strstart); - } - - // Find the longest match, discarding those <= prev_length. - // At this point we have always match_length < MIN_MATCH - - if (hash_head != 0L && ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD) - { - // To simplify the code, we prevent matches with the string - // of window index 0 (in particular we have to avoid a match - // of the string with itself at the start of the input file). - if (compressionStrategy != CompressionStrategy.HuffmanOnly) - { - match_length = longest_match(hash_head); - } - // longest_match() sets match_start - } - if (match_length >= MIN_MATCH) - { - // check_match(strstart, match_start, match_length); - - bflush = _tr_tally(strstart - match_start, match_length - MIN_MATCH); - - lookahead -= match_length; - - // Insert new strings in the hash table only if the match length - // is not too large. This saves time but degrades compression. - if (match_length <= config.MaxLazy && lookahead >= MIN_MATCH) - { - match_length--; // string at strstart already in hash table - do - { - strstart++; - - ins_h = ((ins_h << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask; - // prev[strstart&w_mask]=hash_head=head[ins_h]; - hash_head = (head[ins_h] & 0xffff); - prev[strstart & w_mask] = head[ins_h]; - head[ins_h] = unchecked((short)strstart); - - // strstart never exceeds WSIZE-MAX_MATCH, so there are - // always MIN_MATCH bytes ahead. - } - while (--match_length != 0); - strstart++; - } - else - { - strstart += match_length; - match_length = 0; - ins_h = window[strstart] & 0xff; - - ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask; - // If lookahead < MIN_MATCH, ins_h is garbage, but it does not - // matter since it will be recomputed at next deflate call. - } - } - else - { - // No match, output a literal byte - - bflush = _tr_tally(0, window[strstart] & 0xff); - lookahead--; - strstart++; - } - if (bflush) - { - flush_block_only(false); - if (_codec.AvailableBytesOut == 0) - return BlockState.NeedMore; - } - } - - flush_block_only(flush == FlushType.Finish); - if (_codec.AvailableBytesOut == 0) - { - if (flush == FlushType.Finish) - return BlockState.FinishStarted; - else - return BlockState.NeedMore; - } - return flush == FlushType.Finish ? BlockState.FinishDone : BlockState.BlockDone; - } - - // Same as above, but achieves better compression. We use a lazy - // evaluation for matches: a match is finally adopted only if there is - // no better match at the next window position. - internal BlockState DeflateSlow(FlushType flush) - { - // short hash_head = 0; // head of hash chain - int hash_head = 0; // head of hash chain - bool bflush; // set if current block must be flushed - - // Process the input block. - while (true) - { - // Make sure that we always have enough lookahead, except - // at the end of the input file. We need MAX_MATCH bytes - // for the next match, plus MIN_MATCH bytes to insert the - // string following the next match. - - if (lookahead < MIN_LOOKAHEAD) - { - _fillWindow(); - if (lookahead < MIN_LOOKAHEAD && flush == FlushType.None) - return BlockState.NeedMore; - - if (lookahead == 0) - break; // flush the current block - } - - // Insert the string window[strstart .. strstart+2] in the - // dictionary, and set hash_head to the head of the hash chain: - - if (lookahead >= MIN_MATCH) - { - ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask; - // prev[strstart&w_mask]=hash_head=head[ins_h]; - hash_head = (head[ins_h] & 0xffff); - prev[strstart & w_mask] = head[ins_h]; - head[ins_h] = unchecked((short)strstart); - } - - // Find the longest match, discarding those <= prev_length. - prev_length = match_length; - prev_match = match_start; - match_length = MIN_MATCH - 1; - - if (hash_head != 0 && prev_length < config.MaxLazy && - ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD) - { - // To simplify the code, we prevent matches with the string - // of window index 0 (in particular we have to avoid a match - // of the string with itself at the start of the input file). - - if (compressionStrategy != CompressionStrategy.HuffmanOnly) - { - match_length = longest_match(hash_head); - } - // longest_match() sets match_start - - if (match_length <= 5 && (compressionStrategy == CompressionStrategy.Filtered || - (match_length == MIN_MATCH && strstart - match_start > 4096))) - { - - // If prev_match is also MIN_MATCH, match_start is garbage - // but we will ignore the current match anyway. - match_length = MIN_MATCH - 1; - } - } - - // If there was a match at the previous step and the current - // match is not better, output the previous match: - if (prev_length >= MIN_MATCH && match_length <= prev_length) - { - int max_insert = strstart + lookahead - MIN_MATCH; - // Do not insert strings in hash table beyond this. - - // check_match(strstart-1, prev_match, prev_length); - - bflush = _tr_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH); - - // Insert in hash table all strings up to the end of the match. - // strstart-1 and strstart are already inserted. If there is not - // enough lookahead, the last two strings are not inserted in - // the hash table. - lookahead -= (prev_length - 1); - prev_length -= 2; - do - { - if (++strstart <= max_insert) - { - ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask; - //prev[strstart&w_mask]=hash_head=head[ins_h]; - hash_head = (head[ins_h] & 0xffff); - prev[strstart & w_mask] = head[ins_h]; - head[ins_h] = unchecked((short)strstart); - } - } - while (--prev_length != 0); - match_available = 0; - match_length = MIN_MATCH - 1; - strstart++; - - if (bflush) - { - flush_block_only(false); - if (_codec.AvailableBytesOut == 0) - return BlockState.NeedMore; - } - } - else if (match_available != 0) - { - - // If there was no match at the previous position, output a - // single literal. If there was a match but the current match - // is longer, truncate the previous match to a single literal. - - bflush = _tr_tally(0, window[strstart - 1] & 0xff); - - if (bflush) - { - flush_block_only(false); - } - strstart++; - lookahead--; - if (_codec.AvailableBytesOut == 0) - return BlockState.NeedMore; - } - else - { - // There is no previous match to compare with, wait for - // the next step to decide. - - match_available = 1; - strstart++; - lookahead--; - } - } - - if (match_available != 0) - { - bflush = _tr_tally(0, window[strstart - 1] & 0xff); - match_available = 0; - } - flush_block_only(flush == FlushType.Finish); - - if (_codec.AvailableBytesOut == 0) - { - if (flush == FlushType.Finish) - return BlockState.FinishStarted; - else - return BlockState.NeedMore; - } - - return flush == FlushType.Finish ? BlockState.FinishDone : BlockState.BlockDone; - } - - - internal int longest_match(int cur_match) - { - int chain_length = config.MaxChainLength; // max hash chain length - int scan = strstart; // current string - int match; // matched string - int len; // length of current match - int best_len = prev_length; // best match length so far - int limit = strstart > (w_size - MIN_LOOKAHEAD) ? strstart - (w_size - MIN_LOOKAHEAD) : 0; - - int niceLength = config.NiceLength; - - // Stop when cur_match becomes <= limit. To simplify the code, - // we prevent matches with the string of window index 0. - - int wmask = w_mask; - - int strend = strstart + MAX_MATCH; - byte scan_end1 = window[scan + best_len - 1]; - byte scan_end = window[scan + best_len]; - - // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. - // It is easy to get rid of this optimization if necessary. - - // Do not waste too much time if we already have a good match: - if (prev_length >= config.GoodLength) - { - chain_length >>= 2; - } - - // Do not look for matches beyond the end of the input. This is necessary - // to make deflate deterministic. - if (niceLength > lookahead) - niceLength = lookahead; - - do - { - match = cur_match; - - // Skip to next match if the match length cannot increase - // or if the match length is less than 2: - if (window[match + best_len] != scan_end || - window[match + best_len - 1] != scan_end1 || - window[match] != window[scan] || - window[++match] != window[scan + 1]) - continue; - - // The check at best_len-1 can be removed because it will be made - // again later. (This heuristic is not always a win.) - // It is not necessary to compare scan[2] and match[2] since they - // are always equal when the other bytes match, given that - // the hash keys are equal and that HASH_BITS >= 8. - scan += 2; match++; - - // We check for insufficient lookahead only every 8th comparison; - // the 256th check will be made at strstart+258. - do - { - } - while (window[++scan] == window[++match] && - window[++scan] == window[++match] && - window[++scan] == window[++match] && - window[++scan] == window[++match] && - window[++scan] == window[++match] && - window[++scan] == window[++match] && - window[++scan] == window[++match] && - window[++scan] == window[++match] && scan < strend); - - len = MAX_MATCH - (int)(strend - scan); - scan = strend - MAX_MATCH; - - if (len > best_len) - { - match_start = cur_match; - best_len = len; - if (len >= niceLength) - break; - scan_end1 = window[scan + best_len - 1]; - scan_end = window[scan + best_len]; - } - } - while ((cur_match = (prev[cur_match & wmask] & 0xffff)) > limit && --chain_length != 0); - - if (best_len <= lookahead) - return best_len; - return lookahead; - } - - - private bool Rfc1950BytesEmitted = false; - private bool _WantRfc1950HeaderBytes = true; - internal bool WantRfc1950HeaderBytes - { - get { return _WantRfc1950HeaderBytes; } - set { _WantRfc1950HeaderBytes = value; } - } - - - internal int Initialize(ZlibCodec codec, CompressionLevel level) - { - return Initialize(codec, level, ZlibConstants.WindowBitsMax); - } - - internal int Initialize(ZlibCodec codec, CompressionLevel level, int bits) - { - return Initialize(codec, level, bits, MEM_LEVEL_DEFAULT, CompressionStrategy.Default); - } - - internal int Initialize(ZlibCodec codec, CompressionLevel level, int bits, CompressionStrategy compressionStrategy) - { - return Initialize(codec, level, bits, MEM_LEVEL_DEFAULT, compressionStrategy); - } - - internal int Initialize(ZlibCodec codec, CompressionLevel level, int windowBits, int memLevel, CompressionStrategy strategy) - { - _codec = codec; - _codec.Message = null; - - // validation - if (windowBits < 9 || windowBits > 15) - throw new ZlibException("windowBits must be in the range 9..15."); - - if (memLevel < 1 || memLevel > MEM_LEVEL_MAX) - throw new ZlibException(String.Format("memLevel must be in the range 1.. {0}", MEM_LEVEL_MAX)); - - _codec.dstate = this; - - w_bits = windowBits; - w_size = 1 << w_bits; - w_mask = w_size - 1; - - hash_bits = memLevel + 7; - hash_size = 1 << hash_bits; - hash_mask = hash_size - 1; - hash_shift = ((hash_bits + MIN_MATCH - 1) / MIN_MATCH); - - window = new byte[w_size * 2]; - prev = new short[w_size]; - head = new short[hash_size]; - - // for memLevel==8, this will be 16384, 16k - lit_bufsize = 1 << (memLevel + 6); - - // Use a single array as the buffer for data pending compression, - // the output distance codes, and the output length codes (aka tree). - // orig comment: This works just fine since the average - // output size for (length,distance) codes is <= 24 bits. - pending = new byte[lit_bufsize * 4]; - _distanceOffset = lit_bufsize; - _lengthOffset = (1 + 2) * lit_bufsize; - - // So, for memLevel 8, the length of the pending buffer is 65536. 64k. - // The first 16k are pending bytes. - // The middle slice, of 32k, is used for distance codes. - // The final 16k are length codes. - - this.compressionLevel = level; - this.compressionStrategy = strategy; - - Reset(); - return ZlibConstants.Z_OK; - } - - - internal void Reset() - { - _codec.TotalBytesIn = _codec.TotalBytesOut = 0; - _codec.Message = null; - //strm.data_type = Z_UNKNOWN; - - pendingCount = 0; - nextPending = 0; - - Rfc1950BytesEmitted = false; - - status = (WantRfc1950HeaderBytes) ? INIT_STATE : BUSY_STATE; - _codec._Adler32 = Adler.Adler32(0, null, 0, 0); - - last_flush = (int)FlushType.None; - - _InitializeTreeData(); - _InitializeLazyMatch(); - } - - - internal int End() - { - if (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE) - { - return ZlibConstants.Z_STREAM_ERROR; - } - // Deallocate in reverse order of allocations: - pending = null; - head = null; - prev = null; - window = null; - // free - // dstate=null; - return status == BUSY_STATE ? ZlibConstants.Z_DATA_ERROR : ZlibConstants.Z_OK; - } - - - private void SetDeflater() - { - switch (config.Flavor) - { - case DeflateFlavor.Store: - DeflateFunction = DeflateNone; - break; - case DeflateFlavor.Fast: - DeflateFunction = DeflateFast; - break; - case DeflateFlavor.Slow: - DeflateFunction = DeflateSlow; - break; - } - } - - - internal int SetParams(CompressionLevel level, CompressionStrategy strategy) - { - int result = ZlibConstants.Z_OK; - - if (compressionLevel != level) - { - Config newConfig = Config.Lookup(level); - - // change in the deflate flavor (Fast vs slow vs none)? - if (newConfig.Flavor != config.Flavor && _codec.TotalBytesIn != 0) - { - // Flush the last buffer: - result = _codec.Deflate(FlushType.Partial); - } - - compressionLevel = level; - config = newConfig; - SetDeflater(); - } - - // no need to flush with change in strategy? Really? - compressionStrategy = strategy; - - return result; - } - - - internal int SetDictionary(byte[] dictionary) - { - int length = dictionary.Length; - int index = 0; - - if (dictionary == null || status != INIT_STATE) - throw new ZlibException("Stream error."); - - _codec._Adler32 = Adler.Adler32(_codec._Adler32, dictionary, 0, dictionary.Length); - - if (length < MIN_MATCH) - return ZlibConstants.Z_OK; - if (length > w_size - MIN_LOOKAHEAD) - { - length = w_size - MIN_LOOKAHEAD; - index = dictionary.Length - length; // use the tail of the dictionary - } - Array.Copy(dictionary, index, window, 0, length); - strstart = length; - block_start = length; - - // Insert all strings in the hash table (except for the last two bytes). - // s->lookahead stays null, so s->ins_h will be recomputed at the next - // call of fill_window. - - ins_h = window[0] & 0xff; - ins_h = (((ins_h) << hash_shift) ^ (window[1] & 0xff)) & hash_mask; - - for (int n = 0; n <= length - MIN_MATCH; n++) - { - ins_h = (((ins_h) << hash_shift) ^ (window[(n) + (MIN_MATCH - 1)] & 0xff)) & hash_mask; - prev[n & w_mask] = head[ins_h]; - head[ins_h] = (short)n; - } - return ZlibConstants.Z_OK; - } - - - - internal int Deflate(FlushType flush) - { - int old_flush; - - if (_codec.OutputBuffer == null || - (_codec.InputBuffer == null && _codec.AvailableBytesIn != 0) || - (status == FINISH_STATE && flush != FlushType.Finish)) - { - _codec.Message = _ErrorMessage[ZlibConstants.Z_NEED_DICT - (ZlibConstants.Z_STREAM_ERROR)]; - throw new ZlibException(String.Format("Something is fishy. [{0}]", _codec.Message)); - } - if (_codec.AvailableBytesOut == 0) - { - _codec.Message = _ErrorMessage[ZlibConstants.Z_NEED_DICT - (ZlibConstants.Z_BUF_ERROR)]; - throw new ZlibException("OutputBuffer is full (AvailableBytesOut == 0)"); - } - - old_flush = last_flush; - last_flush = (int)flush; - - // Write the zlib (rfc1950) header bytes - if (status == INIT_STATE) - { - int header = (Z_DEFLATED + ((w_bits - 8) << 4)) << 8; - int level_flags = (((int)compressionLevel - 1) & 0xff) >> 1; - - if (level_flags > 3) - level_flags = 3; - header |= (level_flags << 6); - if (strstart != 0) - header |= PRESET_DICT; - header += 31 - (header % 31); - - status = BUSY_STATE; - //putShortMSB(header); - unchecked - { - pending[pendingCount++] = (byte)(header >> 8); - pending[pendingCount++] = (byte)header; - } - // Save the adler32 of the preset dictionary: - if (strstart != 0) - { - pending[pendingCount++] = (byte)((_codec._Adler32 & 0xFF000000) >> 24); - pending[pendingCount++] = (byte)((_codec._Adler32 & 0x00FF0000) >> 16); - pending[pendingCount++] = (byte)((_codec._Adler32 & 0x0000FF00) >> 8); - pending[pendingCount++] = (byte)(_codec._Adler32 & 0x000000FF); - } - _codec._Adler32 = Adler.Adler32(0, null, 0, 0); - } - - // Flush as much pending output as possible - if (pendingCount != 0) - { - _codec.flush_pending(); - if (_codec.AvailableBytesOut == 0) - { - //System.out.println(" avail_out==0"); - // Since avail_out is 0, deflate will be called again with - // more output space, but possibly with both pending and - // avail_in equal to zero. There won't be anything to do, - // but this is not an error situation so make sure we - // return OK instead of BUF_ERROR at next call of deflate: - last_flush = -1; - return ZlibConstants.Z_OK; - } - - // Make sure there is something to do and avoid duplicate consecutive - // flushes. For repeated and useless calls with Z_FINISH, we keep - // returning Z_STREAM_END instead of Z_BUFF_ERROR. - } - else if (_codec.AvailableBytesIn == 0 && - (int)flush <= old_flush && - flush != FlushType.Finish) - { - // workitem 8557 - // - // Not sure why this needs to be an error. pendingCount == 0, which - // means there's nothing to deflate. And the caller has not asked - // for a FlushType.Finish, but... that seems very non-fatal. We - // can just say "OK" and do nothing. - - // _codec.Message = z_errmsg[ZlibConstants.Z_NEED_DICT - (ZlibConstants.Z_BUF_ERROR)]; - // throw new ZlibException("AvailableBytesIn == 0 && flush<=old_flush && flush != FlushType.Finish"); - - return ZlibConstants.Z_OK; - } - - // User must not provide more input after the first FINISH: - if (status == FINISH_STATE && _codec.AvailableBytesIn != 0) - { - _codec.Message = _ErrorMessage[ZlibConstants.Z_NEED_DICT - (ZlibConstants.Z_BUF_ERROR)]; - throw new ZlibException("status == FINISH_STATE && _codec.AvailableBytesIn != 0"); - } - - // Start a new block or continue the current one. - if (_codec.AvailableBytesIn != 0 || lookahead != 0 || (flush != FlushType.None && status != FINISH_STATE)) - { - BlockState bstate = DeflateFunction(flush); - - if (bstate == BlockState.FinishStarted || bstate == BlockState.FinishDone) - { - status = FINISH_STATE; - } - if (bstate == BlockState.NeedMore || bstate == BlockState.FinishStarted) - { - if (_codec.AvailableBytesOut == 0) - { - last_flush = -1; // avoid BUF_ERROR next call, see above - } - return ZlibConstants.Z_OK; - // If flush != Z_NO_FLUSH && avail_out == 0, the next call - // of deflate should use the same flush parameter to make sure - // that the flush is complete. So we don't have to output an - // empty block here, this will be done at next call. This also - // ensures that for a very small output buffer, we emit at most - // one empty block. - } - - if (bstate == BlockState.BlockDone) - { - if (flush == FlushType.Partial) - { - _tr_align(); - } - else - { - // FlushType.Full or FlushType.Sync - _tr_stored_block(0, 0, false); - // For a full flush, this empty block will be recognized - // as a special marker by inflate_sync(). - if (flush == FlushType.Full) - { - // clear hash (forget the history) - for (int i = 0; i < hash_size; i++) - head[i] = 0; - } - } - _codec.flush_pending(); - if (_codec.AvailableBytesOut == 0) - { - last_flush = -1; // avoid BUF_ERROR at next call, see above - return ZlibConstants.Z_OK; - } - } - } - - if (flush != FlushType.Finish) - return ZlibConstants.Z_OK; - - if (!WantRfc1950HeaderBytes || Rfc1950BytesEmitted) - return ZlibConstants.Z_STREAM_END; - - // Write the zlib trailer (adler32) - pending[pendingCount++] = (byte)((_codec._Adler32 & 0xFF000000) >> 24); - pending[pendingCount++] = (byte)((_codec._Adler32 & 0x00FF0000) >> 16); - pending[pendingCount++] = (byte)((_codec._Adler32 & 0x0000FF00) >> 8); - pending[pendingCount++] = (byte)(_codec._Adler32 & 0x000000FF); - //putShortMSB((int)(SharedUtils.URShift(_codec._Adler32, 16))); - //putShortMSB((int)(_codec._Adler32 & 0xffff)); - - _codec.flush_pending(); - - // If avail_out is zero, the application will call deflate again - // to flush the rest. - - Rfc1950BytesEmitted = true; // write the trailer only once! - - return pendingCount != 0 ? ZlibConstants.Z_OK : ZlibConstants.Z_STREAM_END; - } - - } -} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/Compression/DeflateStream.cs b/MinecraftClient/Protocol/Handlers/Compression/DeflateStream.cs deleted file mode 100644 index 05362d41..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/DeflateStream.cs +++ /dev/null @@ -1,740 +0,0 @@ -// DeflateStream.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2009-2010 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:48:11> -// -// ------------------------------------------------------------------ -// -// This module defines the DeflateStream class, which can be used as a replacement for -// the System.IO.Compression.DeflateStream class in the .NET BCL. -// -// ------------------------------------------------------------------ - - -using System; - -namespace Ionic.Zlib -{ - /// - /// A class for compressing and decompressing streams using the Deflate algorithm. - /// - /// - /// - /// - /// - /// The DeflateStream is a Decorator on a . It adds DEFLATE compression or decompression to any - /// stream. - /// - /// - /// - /// Using this stream, applications can compress or decompress data via stream - /// Read and Write operations. Either compresssion or decompression - /// can occur through either reading or writing. The compression format used is - /// DEFLATE, which is documented in IETF RFC 1951, "DEFLATE - /// Compressed Data Format Specification version 1.3.". - /// - /// - /// - /// This class is similar to , except that - /// ZlibStream adds the RFC - /// 1950 - ZLIB framing bytes to a compressed stream when compressing, or - /// expects the RFC1950 framing bytes when decompressing. The DeflateStream - /// does not. - /// - /// - /// - /// - /// - /// - public class DeflateStream : System.IO.Stream - { - internal ZlibBaseStream _baseStream; - internal System.IO.Stream _innerStream; - bool _disposed; - - /// - /// Create a DeflateStream using the specified CompressionMode. - /// - /// - /// - /// When mode is CompressionMode.Compress, the DeflateStream will use - /// the default compression level. The "captive" stream will be closed when - /// the DeflateStream is closed. - /// - /// - /// - /// This example uses a DeflateStream to compress data from a file, and writes - /// the compressed data to another file. - /// - /// using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) - /// { - /// using (var raw = System.IO.File.Create(fileToCompress + ".deflated")) - /// { - /// using (Stream compressor = new DeflateStream(raw, CompressionMode.Compress)) - /// { - /// byte[] buffer = new byte[WORKING_BUFFER_SIZE]; - /// int n; - /// while ((n= input.Read(buffer, 0, buffer.Length)) != 0) - /// { - /// compressor.Write(buffer, 0, n); - /// } - /// } - /// } - /// } - /// - /// - /// - /// Using input As Stream = File.OpenRead(fileToCompress) - /// Using raw As FileStream = File.Create(fileToCompress & ".deflated") - /// Using compressor As Stream = New DeflateStream(raw, CompressionMode.Compress) - /// Dim buffer As Byte() = New Byte(4096) {} - /// Dim n As Integer = -1 - /// Do While (n <> 0) - /// If (n > 0) Then - /// compressor.Write(buffer, 0, n) - /// End If - /// n = input.Read(buffer, 0, buffer.Length) - /// Loop - /// End Using - /// End Using - /// End Using - /// - /// - /// The stream which will be read or written. - /// Indicates whether the DeflateStream will compress or decompress. - public DeflateStream(System.IO.Stream stream, CompressionMode mode) - : this(stream, mode, CompressionLevel.Default, false) - { - } - - /// - /// Create a DeflateStream using the specified CompressionMode and the specified CompressionLevel. - /// - /// - /// - /// - /// - /// When mode is CompressionMode.Decompress, the level parameter is - /// ignored. The "captive" stream will be closed when the DeflateStream is - /// closed. - /// - /// - /// - /// - /// - /// - /// This example uses a DeflateStream to compress data from a file, and writes - /// the compressed data to another file. - /// - /// - /// using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) - /// { - /// using (var raw = System.IO.File.Create(fileToCompress + ".deflated")) - /// { - /// using (Stream compressor = new DeflateStream(raw, - /// CompressionMode.Compress, - /// CompressionLevel.BestCompression)) - /// { - /// byte[] buffer = new byte[WORKING_BUFFER_SIZE]; - /// int n= -1; - /// while (n != 0) - /// { - /// if (n > 0) - /// compressor.Write(buffer, 0, n); - /// n= input.Read(buffer, 0, buffer.Length); - /// } - /// } - /// } - /// } - /// - /// - /// - /// Using input As Stream = File.OpenRead(fileToCompress) - /// Using raw As FileStream = File.Create(fileToCompress & ".deflated") - /// Using compressor As Stream = New DeflateStream(raw, CompressionMode.Compress, CompressionLevel.BestCompression) - /// Dim buffer As Byte() = New Byte(4096) {} - /// Dim n As Integer = -1 - /// Do While (n <> 0) - /// If (n > 0) Then - /// compressor.Write(buffer, 0, n) - /// End If - /// n = input.Read(buffer, 0, buffer.Length) - /// Loop - /// End Using - /// End Using - /// End Using - /// - /// - /// The stream to be read or written while deflating or inflating. - /// Indicates whether the DeflateStream will compress or decompress. - /// A tuning knob to trade speed for effectiveness. - public DeflateStream(System.IO.Stream stream, CompressionMode mode, CompressionLevel level) - : this(stream, mode, level, false) - { - } - - /// - /// Create a DeflateStream using the specified - /// CompressionMode, and explicitly specify whether the - /// stream should be left open after Deflation or Inflation. - /// - /// - /// - /// - /// - /// This constructor allows the application to request that the captive stream - /// remain open after the deflation or inflation occurs. By default, after - /// Close() is called on the stream, the captive stream is also - /// closed. In some cases this is not desired, for example if the stream is a - /// memory stream that will be re-read after compression. Specify true for - /// the parameter to leave the stream open. - /// - /// - /// - /// The DeflateStream will use the default compression level. - /// - /// - /// - /// See the other overloads of this constructor for example code. - /// - /// - /// - /// - /// The stream which will be read or written. This is called the - /// "captive" stream in other places in this documentation. - /// - /// - /// - /// Indicates whether the DeflateStream will compress or decompress. - /// - /// - /// true if the application would like the stream to - /// remain open after inflation/deflation. - public DeflateStream(System.IO.Stream stream, CompressionMode mode, bool leaveOpen) - : this(stream, mode, CompressionLevel.Default, leaveOpen) - { - } - - /// - /// Create a DeflateStream using the specified CompressionMode - /// and the specified CompressionLevel, and explicitly specify whether - /// the stream should be left open after Deflation or Inflation. - /// - /// - /// - /// - /// - /// When mode is CompressionMode.Decompress, the level parameter is ignored. - /// - /// - /// - /// This constructor allows the application to request that the captive stream - /// remain open after the deflation or inflation occurs. By default, after - /// Close() is called on the stream, the captive stream is also - /// closed. In some cases this is not desired, for example if the stream is a - /// that will be re-read after - /// compression. Specify true for the parameter - /// to leave the stream open. - /// - /// - /// - /// - /// - /// - /// This example shows how to use a DeflateStream to compress data from - /// a file, and store the compressed data into another file. - /// - /// - /// using (var output = System.IO.File.Create(fileToCompress + ".deflated")) - /// { - /// using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) - /// { - /// using (Stream compressor = new DeflateStream(output, CompressionMode.Compress, CompressionLevel.BestCompression, true)) - /// { - /// byte[] buffer = new byte[WORKING_BUFFER_SIZE]; - /// int n= -1; - /// while (n != 0) - /// { - /// if (n > 0) - /// compressor.Write(buffer, 0, n); - /// n= input.Read(buffer, 0, buffer.Length); - /// } - /// } - /// } - /// // can write additional data to the output stream here - /// } - /// - /// - /// - /// Using output As FileStream = File.Create(fileToCompress & ".deflated") - /// Using input As Stream = File.OpenRead(fileToCompress) - /// Using compressor As Stream = New DeflateStream(output, CompressionMode.Compress, CompressionLevel.BestCompression, True) - /// Dim buffer As Byte() = New Byte(4096) {} - /// Dim n As Integer = -1 - /// Do While (n <> 0) - /// If (n > 0) Then - /// compressor.Write(buffer, 0, n) - /// End If - /// n = input.Read(buffer, 0, buffer.Length) - /// Loop - /// End Using - /// End Using - /// ' can write additional data to the output stream here. - /// End Using - /// - /// - /// The stream which will be read or written. - /// Indicates whether the DeflateStream will compress or decompress. - /// true if the application would like the stream to remain open after inflation/deflation. - /// A tuning knob to trade speed for effectiveness. - public DeflateStream(System.IO.Stream stream, CompressionMode mode, CompressionLevel level, bool leaveOpen) - { - _innerStream = stream; - _baseStream = new ZlibBaseStream(stream, mode, level, ZlibStreamFlavor.DEFLATE, leaveOpen); - } - - #region Zlib properties - - /// - /// This property sets the flush behavior on the stream. - /// - /// See the ZLIB documentation for the meaning of the flush behavior. - /// - virtual public FlushType FlushMode - { - get { return (this._baseStream._flushMode); } - set - { - if (_disposed) throw new ObjectDisposedException("DeflateStream"); - this._baseStream._flushMode = value; - } - } - - /// - /// The size of the working buffer for the compression codec. - /// - /// - /// - /// - /// The working buffer is used for all stream operations. The default size is - /// 1024 bytes. The minimum size is 128 bytes. You may get better performance - /// with a larger buffer. Then again, you might not. You would have to test - /// it. - /// - /// - /// - /// Set this before the first call to Read() or Write() on the - /// stream. If you try to set it afterwards, it will throw. - /// - /// - public int BufferSize - { - get - { - return this._baseStream._bufferSize; - } - set - { - if (_disposed) throw new ObjectDisposedException("DeflateStream"); - if (this._baseStream._workingBuffer != null) - throw new ZlibException("The working buffer is already set."); - if (value < ZlibConstants.WorkingBufferSizeMin) - throw new ZlibException(String.Format("Don't be silly. {0} bytes?? Use a bigger buffer, at least {1}.", value, ZlibConstants.WorkingBufferSizeMin)); - this._baseStream._bufferSize = value; - } - } - - /// - /// The ZLIB strategy to be used during compression. - /// - /// - /// - /// By tweaking this parameter, you may be able to optimize the compression for - /// data with particular characteristics. - /// - public CompressionStrategy Strategy - { - get - { - return this._baseStream.Strategy; - } - set - { - if (_disposed) throw new ObjectDisposedException("DeflateStream"); - this._baseStream.Strategy = value; - } - } - - /// Returns the total number of bytes input so far. - virtual public long TotalIn - { - get - { - return this._baseStream._z.TotalBytesIn; - } - } - - /// Returns the total number of bytes output so far. - virtual public long TotalOut - { - get - { - return this._baseStream._z.TotalBytesOut; - } - } - - #endregion - - #region System.IO.Stream methods - /// - /// Dispose the stream. - /// - /// - /// - /// This may or may not result in a Close() call on the captive - /// stream. See the constructors that have a leaveOpen parameter - /// for more information. - /// - /// - /// Application code won't call this code directly. This method may be - /// invoked in two distinct scenarios. If disposing == true, the method - /// has been called directly or indirectly by a user's code, for example - /// via the public Dispose() method. In this case, both managed and - /// unmanaged resources can be referenced and disposed. If disposing == - /// false, the method has been called by the runtime from inside the - /// object finalizer and this method should not reference other objects; - /// in that case only unmanaged resources must be referenced or - /// disposed. - /// - /// - /// - /// true if the Dispose method was invoked by user code. - /// - protected override void Dispose(bool disposing) - { - try - { - if (!_disposed) - { - if (disposing && (this._baseStream != null)) - this._baseStream.Close(); - _disposed = true; - } - } - finally - { - base.Dispose(disposing); - } - } - - - - /// - /// Indicates whether the stream can be read. - /// - /// - /// The return value depends on whether the captive stream supports reading. - /// - public override bool CanRead - { - get - { - if (_disposed) throw new ObjectDisposedException("DeflateStream"); - return _baseStream._stream.CanRead; - } - } - - /// - /// Indicates whether the stream supports Seek operations. - /// - /// - /// Always returns false. - /// - public override bool CanSeek - { - get { return false; } - } - - - /// - /// Indicates whether the stream can be written. - /// - /// - /// The return value depends on whether the captive stream supports writing. - /// - public override bool CanWrite - { - get - { - if (_disposed) throw new ObjectDisposedException("DeflateStream"); - return _baseStream._stream.CanWrite; - } - } - - /// - /// Flush the stream. - /// - public override void Flush() - { - if (_disposed) throw new ObjectDisposedException("DeflateStream"); - _baseStream.Flush(); - } - - /// - /// Reading this property always throws a . - /// - public override long Length - { - get { throw new NotImplementedException(); } - } - - /// - /// The position of the stream pointer. - /// - /// - /// - /// Setting this property always throws a . Reading will return the total bytes - /// written out, if used in writing, or the total bytes read in, if used in - /// reading. The count may refer to compressed bytes or uncompressed bytes, - /// depending on how you've used the stream. - /// - public override long Position - { - get - { - if (this._baseStream._streamMode == Ionic.Zlib.ZlibBaseStream.StreamMode.Writer) - return this._baseStream._z.TotalBytesOut; - if (this._baseStream._streamMode == Ionic.Zlib.ZlibBaseStream.StreamMode.Reader) - return this._baseStream._z.TotalBytesIn; - return 0; - } - set { throw new NotImplementedException(); } - } - - /// - /// Read data from the stream. - /// - /// - /// - /// - /// If you wish to use the DeflateStream to compress data while - /// reading, you can create a DeflateStream with - /// CompressionMode.Compress, providing an uncompressed data stream. - /// Then call Read() on that DeflateStream, and the data read will be - /// compressed as you read. If you wish to use the DeflateStream to - /// decompress data while reading, you can create a DeflateStream with - /// CompressionMode.Decompress, providing a readable compressed data - /// stream. Then call Read() on that DeflateStream, and the data read - /// will be decompressed as you read. - /// - /// - /// - /// A DeflateStream can be used for Read() or Write(), but not both. - /// - /// - /// - /// The buffer into which the read data should be placed. - /// the offset within that data array to put the first byte read. - /// the number of bytes to read. - /// the number of bytes actually read - public override int Read(byte[] buffer, int offset, int count) - { - if (_disposed) throw new ObjectDisposedException("DeflateStream"); - return _baseStream.Read(buffer, offset, count); - } - - - /// - /// Calling this method always throws a . - /// - /// this is irrelevant, since it will always throw! - /// this is irrelevant, since it will always throw! - /// irrelevant! - public override long Seek(long offset, System.IO.SeekOrigin origin) - { - throw new NotImplementedException(); - } - - /// - /// Calling this method always throws a . - /// - /// this is irrelevant, since it will always throw! - public override void SetLength(long value) - { - throw new NotImplementedException(); - } - - /// - /// Write data to the stream. - /// - /// - /// - /// - /// If you wish to use the DeflateStream to compress data while - /// writing, you can create a DeflateStream with - /// CompressionMode.Compress, and a writable output stream. Then call - /// Write() on that DeflateStream, providing uncompressed data - /// as input. The data sent to the output stream will be the compressed form - /// of the data written. If you wish to use the DeflateStream to - /// decompress data while writing, you can create a DeflateStream with - /// CompressionMode.Decompress, and a writable output stream. Then - /// call Write() on that stream, providing previously compressed - /// data. The data sent to the output stream will be the decompressed form of - /// the data written. - /// - /// - /// - /// A DeflateStream can be used for Read() or Write(), - /// but not both. - /// - /// - /// - /// - /// The buffer holding data to write to the stream. - /// the offset within that data array to find the first byte to write. - /// the number of bytes to write. - public override void Write(byte[] buffer, int offset, int count) - { - if (_disposed) throw new ObjectDisposedException("DeflateStream"); - _baseStream.Write(buffer, offset, count); - } - #endregion - - - - - /// - /// Compress a string into a byte array using DEFLATE (RFC 1951). - /// - /// - /// - /// Uncompress it with . - /// - /// - /// DeflateStream.UncompressString(byte[]) - /// DeflateStream.CompressBuffer(byte[]) - /// GZipStream.CompressString(string) - /// ZlibStream.CompressString(string) - /// - /// - /// A string to compress. The string will first be encoded - /// using UTF8, then compressed. - /// - /// - /// The string in compressed form - public static byte[] CompressString(String s) - { - using (var ms = new System.IO.MemoryStream()) - { - System.IO.Stream compressor = - new DeflateStream(ms, CompressionMode.Compress, CompressionLevel.BestCompression); - ZlibBaseStream.CompressString(s, compressor); - return ms.ToArray(); - } - } - - - /// - /// Compress a byte array into a new byte array using DEFLATE. - /// - /// - /// - /// Uncompress it with . - /// - /// - /// DeflateStream.CompressString(string) - /// DeflateStream.UncompressBuffer(byte[]) - /// GZipStream.CompressBuffer(byte[]) - /// ZlibStream.CompressBuffer(byte[]) - /// - /// - /// A buffer to compress. - /// - /// - /// The data in compressed form - public static byte[] CompressBuffer(byte[] b) - { - using (var ms = new System.IO.MemoryStream()) - { - System.IO.Stream compressor = - new DeflateStream( ms, CompressionMode.Compress, CompressionLevel.BestCompression ); - - ZlibBaseStream.CompressBuffer(b, compressor); - return ms.ToArray(); - } - } - - - /// - /// Uncompress a DEFLATE'd byte array into a single string. - /// - /// - /// DeflateStream.CompressString(String) - /// DeflateStream.UncompressBuffer(byte[]) - /// GZipStream.UncompressString(byte[]) - /// ZlibStream.UncompressString(byte[]) - /// - /// - /// A buffer containing DEFLATE-compressed data. - /// - /// - /// The uncompressed string - public static String UncompressString(byte[] compressed) - { - using (var input = new System.IO.MemoryStream(compressed)) - { - System.IO.Stream decompressor = - new DeflateStream(input, CompressionMode.Decompress); - - return ZlibBaseStream.UncompressString(compressed, decompressor); - } - } - - - /// - /// Uncompress a DEFLATE'd byte array into a byte array. - /// - /// - /// DeflateStream.CompressBuffer(byte[]) - /// DeflateStream.UncompressString(byte[]) - /// GZipStream.UncompressBuffer(byte[]) - /// ZlibStream.UncompressBuffer(byte[]) - /// - /// - /// A buffer containing data that has been compressed with DEFLATE. - /// - /// - /// The data in uncompressed form - public static byte[] UncompressBuffer(byte[] compressed) - { - using (var input = new System.IO.MemoryStream(compressed)) - { - System.IO.Stream decompressor = - new DeflateStream( input, CompressionMode.Decompress ); - - return ZlibBaseStream.UncompressBuffer(compressed, decompressor); - } - } - - } - -} - diff --git a/MinecraftClient/Protocol/Handlers/Compression/GZipStream.cs b/MinecraftClient/Protocol/Handlers/Compression/GZipStream.cs deleted file mode 100644 index 745e0963..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/GZipStream.cs +++ /dev/null @@ -1,1033 +0,0 @@ -// GZipStream.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation. -// 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-August-08 18:14:39> -// -// ------------------------------------------------------------------ -// -// This module defines the GZipStream class, which can be used as a replacement for -// the System.IO.Compression.GZipStream class in the .NET BCL. NB: The design is not -// completely OO clean: there is some intelligence in the ZlibBaseStream that reads the -// GZip header. -// -// ------------------------------------------------------------------ - - -using System; -using System.IO; - -namespace Ionic.Zlib -{ - /// - /// A class for compressing and decompressing GZIP streams. - /// - /// - /// - /// - /// The GZipStream is a Decorator on a - /// . It adds GZIP compression or decompression to any - /// stream. - /// - /// - /// - /// Like the System.IO.Compression.GZipStream in the .NET Base Class Library, the - /// Ionic.Zlib.GZipStream can compress while writing, or decompress while - /// reading, but not vice versa. The compression method used is GZIP, which is - /// documented in IETF RFC - /// 1952, "GZIP file format specification version 4.3". - /// - /// - /// A GZipStream can be used to decompress data (through Read()) or - /// to compress data (through Write()), but not both. - /// - /// - /// - /// If you wish to use the GZipStream to compress data, you must wrap it - /// around a write-able stream. As you call Write() on the GZipStream, the - /// data will be compressed into the GZIP format. If you want to decompress data, - /// you must wrap the GZipStream around a readable stream that contains an - /// IETF RFC 1952-compliant stream. The data will be decompressed as you call - /// Read() on the GZipStream. - /// - /// - /// - /// Though the GZIP format allows data from multiple files to be concatenated - /// together, this stream handles only a single segment of GZIP format, typically - /// representing a single file. - /// - /// - /// - /// This class is similar to and . - /// ZlibStream handles RFC1950-compliant streams. - /// handles RFC1951-compliant streams. This class handles RFC1952-compliant streams. - /// - /// - /// - /// - /// - /// - public class GZipStream : System.IO.Stream - { - // GZip format - // source: http://tools.ietf.org/html/rfc1952 - // - // header id: 2 bytes 1F 8B - // compress method 1 byte 8= DEFLATE (none other supported) - // flag 1 byte bitfield (See below) - // mtime 4 bytes time_t (seconds since jan 1, 1970 UTC of the file. - // xflg 1 byte 2 = max compress used , 4 = max speed (can be ignored) - // OS 1 byte OS for originating archive. set to 0xFF in compression. - // extra field length 2 bytes optional - only if FEXTRA is set. - // extra field varies - // filename varies optional - if FNAME is set. zero terminated. ISO-8859-1. - // file comment varies optional - if FCOMMENT is set. zero terminated. ISO-8859-1. - // crc16 1 byte optional - present only if FHCRC bit is set - // compressed data varies - // CRC32 4 bytes - // isize 4 bytes data size modulo 2^32 - // - // FLG (FLaGs) - // bit 0 FTEXT - indicates file is ASCII text (can be safely ignored) - // bit 1 FHCRC - there is a CRC16 for the header immediately following the header - // bit 2 FEXTRA - extra fields are present - // bit 3 FNAME - the zero-terminated filename is present. encoding; ISO-8859-1. - // bit 4 FCOMMENT - a zero-terminated file comment is present. encoding: ISO-8859-1 - // bit 5 reserved - // bit 6 reserved - // bit 7 reserved - // - // On consumption: - // Extra field is a bunch of nonsense and can be safely ignored. - // Header CRC and OS, likewise. - // - // on generation: - // all optional fields get 0, except for the OS, which gets 255. - // - - - - /// - /// The comment on the GZIP stream. - /// - /// - /// - /// - /// The GZIP format allows for each file to optionally have an associated - /// comment stored with the file. The comment is encoded with the ISO-8859-1 - /// code page. To include a comment in a GZIP stream you create, set this - /// property before calling Write() for the first time on the - /// GZipStream. - /// - /// - /// - /// When using GZipStream to decompress, you can retrieve this property - /// after the first call to Read(). If no comment has been set in the - /// GZIP bytestream, the Comment property will return null - /// (Nothing in VB). - /// - /// - public String Comment - { - get - { - return _Comment; - } - set - { - if (_disposed) throw new ObjectDisposedException("GZipStream"); - _Comment = value; - } - } - - /// - /// The FileName for the GZIP stream. - /// - /// - /// - /// - /// - /// The GZIP format optionally allows each file to have an associated - /// filename. When compressing data (through Write()), set this - /// FileName before calling Write() the first time on the GZipStream. - /// The actual filename is encoded into the GZIP bytestream with the - /// ISO-8859-1 code page, according to RFC 1952. It is the application's - /// responsibility to insure that the FileName can be encoded and decoded - /// correctly with this code page. - /// - /// - /// - /// When decompressing (through Read()), you can retrieve this value - /// any time after the first Read(). In the case where there was no filename - /// encoded into the GZIP bytestream, the property will return null (Nothing - /// in VB). - /// - /// - public String FileName - { - get { return _FileName; } - set - { - if (_disposed) throw new ObjectDisposedException("GZipStream"); - _FileName = value; - if (_FileName == null) return; - if (_FileName.IndexOf("/") != -1) - { - _FileName = _FileName.Replace("/", "\\"); - } - if (_FileName.EndsWith("\\")) - throw new Exception("Illegal filename"); - if (_FileName.IndexOf("\\") != -1) - { - // trim any leading path - _FileName = Path.GetFileName(_FileName); - } - } - } - - /// - /// The last modified time for the GZIP stream. - /// - /// - /// - /// GZIP allows the storage of a last modified time with each GZIP entry. - /// When compressing data, you can set this before the first call to - /// Write(). When decompressing, you can retrieve this value any time - /// after the first call to Read(). - /// - public DateTime? LastModified; - - /// - /// The CRC on the GZIP stream. - /// - /// - /// This is used for internal error checking. You probably don't need to look at this property. - /// - public int Crc32 { get { return _Crc32; } } - - private int _headerByteCount; - internal ZlibBaseStream _baseStream; - bool _disposed; - bool _firstReadDone; - string _FileName; - string _Comment; - int _Crc32; - - - /// - /// Create a GZipStream using the specified CompressionMode. - /// - /// - /// - /// - /// When mode is CompressionMode.Compress, the GZipStream will use the - /// default compression level. - /// - /// - /// - /// As noted in the class documentation, the CompressionMode (Compress - /// or Decompress) also establishes the "direction" of the stream. A - /// GZipStream with CompressionMode.Compress works only through - /// Write(). A GZipStream with - /// CompressionMode.Decompress works only through Read(). - /// - /// - /// - /// - /// - /// This example shows how to use a GZipStream to compress data. - /// - /// using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) - /// { - /// using (var raw = System.IO.File.Create(outputFile)) - /// { - /// using (Stream compressor = new GZipStream(raw, CompressionMode.Compress)) - /// { - /// byte[] buffer = new byte[WORKING_BUFFER_SIZE]; - /// int n; - /// while ((n= input.Read(buffer, 0, buffer.Length)) != 0) - /// { - /// compressor.Write(buffer, 0, n); - /// } - /// } - /// } - /// } - /// - /// - /// Dim outputFile As String = (fileToCompress & ".compressed") - /// Using input As Stream = File.OpenRead(fileToCompress) - /// Using raw As FileStream = File.Create(outputFile) - /// Using compressor As Stream = New GZipStream(raw, CompressionMode.Compress) - /// Dim buffer As Byte() = New Byte(4096) {} - /// Dim n As Integer = -1 - /// Do While (n <> 0) - /// If (n > 0) Then - /// compressor.Write(buffer, 0, n) - /// End If - /// n = input.Read(buffer, 0, buffer.Length) - /// Loop - /// End Using - /// End Using - /// End Using - /// - /// - /// - /// - /// This example shows how to use a GZipStream to uncompress a file. - /// - /// private void GunZipFile(string filename) - /// { - /// if (!filename.EndsWith(".gz)) - /// throw new ArgumentException("filename"); - /// var DecompressedFile = filename.Substring(0,filename.Length-3); - /// byte[] working = new byte[WORKING_BUFFER_SIZE]; - /// int n= 1; - /// using (System.IO.Stream input = System.IO.File.OpenRead(filename)) - /// { - /// using (Stream decompressor= new Ionic.Zlib.GZipStream(input, CompressionMode.Decompress, true)) - /// { - /// using (var output = System.IO.File.Create(DecompressedFile)) - /// { - /// while (n !=0) - /// { - /// n= decompressor.Read(working, 0, working.Length); - /// if (n > 0) - /// { - /// output.Write(working, 0, n); - /// } - /// } - /// } - /// } - /// } - /// } - /// - /// - /// - /// Private Sub GunZipFile(ByVal filename as String) - /// If Not (filename.EndsWith(".gz)) Then - /// Throw New ArgumentException("filename") - /// End If - /// Dim DecompressedFile as String = filename.Substring(0,filename.Length-3) - /// Dim working(WORKING_BUFFER_SIZE) as Byte - /// Dim n As Integer = 1 - /// Using input As Stream = File.OpenRead(filename) - /// Using decompressor As Stream = new Ionic.Zlib.GZipStream(input, CompressionMode.Decompress, True) - /// Using output As Stream = File.Create(UncompressedFile) - /// Do - /// n= decompressor.Read(working, 0, working.Length) - /// If n > 0 Then - /// output.Write(working, 0, n) - /// End IF - /// Loop While (n > 0) - /// End Using - /// End Using - /// End Using - /// End Sub - /// - /// - /// - /// The stream which will be read or written. - /// Indicates whether the GZipStream will compress or decompress. - public GZipStream(Stream stream, CompressionMode mode) - : this(stream, mode, CompressionLevel.Default, false) - { - } - - /// - /// Create a GZipStream using the specified CompressionMode and - /// the specified CompressionLevel. - /// - /// - /// - /// - /// The CompressionMode (Compress or Decompress) also establishes the - /// "direction" of the stream. A GZipStream with - /// CompressionMode.Compress works only through Write(). A - /// GZipStream with CompressionMode.Decompress works only - /// through Read(). - /// - /// - /// - /// - /// - /// - /// This example shows how to use a GZipStream to compress a file into a .gz file. - /// - /// - /// using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) - /// { - /// using (var raw = System.IO.File.Create(fileToCompress + ".gz")) - /// { - /// using (Stream compressor = new GZipStream(raw, - /// CompressionMode.Compress, - /// CompressionLevel.BestCompression)) - /// { - /// byte[] buffer = new byte[WORKING_BUFFER_SIZE]; - /// int n; - /// while ((n= input.Read(buffer, 0, buffer.Length)) != 0) - /// { - /// compressor.Write(buffer, 0, n); - /// } - /// } - /// } - /// } - /// - /// - /// - /// Using input As Stream = File.OpenRead(fileToCompress) - /// Using raw As FileStream = File.Create(fileToCompress & ".gz") - /// Using compressor As Stream = New GZipStream(raw, CompressionMode.Compress, CompressionLevel.BestCompression) - /// Dim buffer As Byte() = New Byte(4096) {} - /// Dim n As Integer = -1 - /// Do While (n <> 0) - /// If (n > 0) Then - /// compressor.Write(buffer, 0, n) - /// End If - /// n = input.Read(buffer, 0, buffer.Length) - /// Loop - /// End Using - /// End Using - /// End Using - /// - /// - /// The stream to be read or written while deflating or inflating. - /// Indicates whether the GZipStream will compress or decompress. - /// A tuning knob to trade speed for effectiveness. - public GZipStream(Stream stream, CompressionMode mode, CompressionLevel level) - : this(stream, mode, level, false) - { - } - - /// - /// Create a GZipStream using the specified CompressionMode, and - /// explicitly specify whether the stream should be left open after Deflation - /// or Inflation. - /// - /// - /// - /// - /// This constructor allows the application to request that the captive stream - /// remain open after the deflation or inflation occurs. By default, after - /// Close() is called on the stream, the captive stream is also - /// closed. In some cases this is not desired, for example if the stream is a - /// memory stream that will be re-read after compressed data has been written - /// to it. Specify true for the parameter to leave - /// the stream open. - /// - /// - /// - /// The (Compress or Decompress) also - /// establishes the "direction" of the stream. A GZipStream with - /// CompressionMode.Compress works only through Write(). A GZipStream - /// with CompressionMode.Decompress works only through Read(). - /// - /// - /// - /// The GZipStream will use the default compression level. If you want - /// to specify the compression level, see . - /// - /// - /// - /// See the other overloads of this constructor for example code. - /// - /// - /// - /// - /// - /// The stream which will be read or written. This is called the "captive" - /// stream in other places in this documentation. - /// - /// - /// Indicates whether the GZipStream will compress or decompress. - /// - /// - /// - /// true if the application would like the base stream to remain open after - /// inflation/deflation. - /// - public GZipStream(Stream stream, CompressionMode mode, bool leaveOpen) - : this(stream, mode, CompressionLevel.Default, leaveOpen) - { - } - - /// - /// Create a GZipStream using the specified CompressionMode and the - /// specified CompressionLevel, and explicitly specify whether the - /// stream should be left open after Deflation or Inflation. - /// - /// - /// - /// - /// - /// This constructor allows the application to request that the captive stream - /// remain open after the deflation or inflation occurs. By default, after - /// Close() is called on the stream, the captive stream is also - /// closed. In some cases this is not desired, for example if the stream is a - /// memory stream that will be re-read after compressed data has been written - /// to it. Specify true for the parameter to - /// leave the stream open. - /// - /// - /// - /// As noted in the class documentation, the CompressionMode (Compress - /// or Decompress) also establishes the "direction" of the stream. A - /// GZipStream with CompressionMode.Compress works only through - /// Write(). A GZipStream with CompressionMode.Decompress works only - /// through Read(). - /// - /// - /// - /// - /// - /// This example shows how to use a GZipStream to compress data. - /// - /// using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) - /// { - /// using (var raw = System.IO.File.Create(outputFile)) - /// { - /// using (Stream compressor = new GZipStream(raw, CompressionMode.Compress, CompressionLevel.BestCompression, true)) - /// { - /// byte[] buffer = new byte[WORKING_BUFFER_SIZE]; - /// int n; - /// while ((n= input.Read(buffer, 0, buffer.Length)) != 0) - /// { - /// compressor.Write(buffer, 0, n); - /// } - /// } - /// } - /// } - /// - /// - /// Dim outputFile As String = (fileToCompress & ".compressed") - /// Using input As Stream = File.OpenRead(fileToCompress) - /// Using raw As FileStream = File.Create(outputFile) - /// Using compressor As Stream = New GZipStream(raw, CompressionMode.Compress, CompressionLevel.BestCompression, True) - /// Dim buffer As Byte() = New Byte(4096) {} - /// Dim n As Integer = -1 - /// Do While (n <> 0) - /// If (n > 0) Then - /// compressor.Write(buffer, 0, n) - /// End If - /// n = input.Read(buffer, 0, buffer.Length) - /// Loop - /// End Using - /// End Using - /// End Using - /// - /// - /// The stream which will be read or written. - /// Indicates whether the GZipStream will compress or decompress. - /// true if the application would like the stream to remain open after inflation/deflation. - /// A tuning knob to trade speed for effectiveness. - public GZipStream(Stream stream, CompressionMode mode, CompressionLevel level, bool leaveOpen) - { - _baseStream = new ZlibBaseStream(stream, mode, level, ZlibStreamFlavor.GZIP, leaveOpen); - } - - #region Zlib properties - - /// - /// This property sets the flush behavior on the stream. - /// - virtual public FlushType FlushMode - { - get { return (this._baseStream._flushMode); } - set { - if (_disposed) throw new ObjectDisposedException("GZipStream"); - this._baseStream._flushMode = value; - } - } - - /// - /// The size of the working buffer for the compression codec. - /// - /// - /// - /// - /// The working buffer is used for all stream operations. The default size is - /// 1024 bytes. The minimum size is 128 bytes. You may get better performance - /// with a larger buffer. Then again, you might not. You would have to test - /// it. - /// - /// - /// - /// Set this before the first call to Read() or Write() on the - /// stream. If you try to set it afterwards, it will throw. - /// - /// - public int BufferSize - { - get - { - return this._baseStream._bufferSize; - } - set - { - if (_disposed) throw new ObjectDisposedException("GZipStream"); - if (this._baseStream._workingBuffer != null) - throw new ZlibException("The working buffer is already set."); - if (value < ZlibConstants.WorkingBufferSizeMin) - throw new ZlibException(String.Format("Don't be silly. {0} bytes?? Use a bigger buffer, at least {1}.", value, ZlibConstants.WorkingBufferSizeMin)); - this._baseStream._bufferSize = value; - } - } - - - /// Returns the total number of bytes input so far. - virtual public long TotalIn - { - get - { - return this._baseStream._z.TotalBytesIn; - } - } - - /// Returns the total number of bytes output so far. - virtual public long TotalOut - { - get - { - return this._baseStream._z.TotalBytesOut; - } - } - - #endregion - - #region Stream methods - - /// - /// Dispose the stream. - /// - /// - /// - /// This may or may not result in a Close() call on the captive - /// stream. See the constructors that have a leaveOpen parameter - /// for more information. - /// - /// - /// This method may be invoked in two distinct scenarios. If disposing - /// == true, the method has been called directly or indirectly by a - /// user's code, for example via the public Dispose() method. In this - /// case, both managed and unmanaged resources can be referenced and - /// disposed. If disposing == false, the method has been called by the - /// runtime from inside the object finalizer and this method should not - /// reference other objects; in that case only unmanaged resources must - /// be referenced or disposed. - /// - /// - /// - /// indicates whether the Dispose method was invoked by user code. - /// - protected override void Dispose(bool disposing) - { - try - { - if (!_disposed) - { - if (disposing && (this._baseStream != null)) - { - this._baseStream.Close(); - this._Crc32 = _baseStream.Crc32; - } - _disposed = true; - } - } - finally - { - base.Dispose(disposing); - } - } - - - /// - /// Indicates whether the stream can be read. - /// - /// - /// The return value depends on whether the captive stream supports reading. - /// - public override bool CanRead - { - get - { - if (_disposed) throw new ObjectDisposedException("GZipStream"); - return _baseStream._stream.CanRead; - } - } - - /// - /// Indicates whether the stream supports Seek operations. - /// - /// - /// Always returns false. - /// - public override bool CanSeek - { - get { return false; } - } - - - /// - /// Indicates whether the stream can be written. - /// - /// - /// The return value depends on whether the captive stream supports writing. - /// - public override bool CanWrite - { - get - { - if (_disposed) throw new ObjectDisposedException("GZipStream"); - return _baseStream._stream.CanWrite; - } - } - - /// - /// Flush the stream. - /// - public override void Flush() - { - if (_disposed) throw new ObjectDisposedException("GZipStream"); - _baseStream.Flush(); - } - - /// - /// Reading this property always throws a . - /// - public override long Length - { - get { throw new NotImplementedException(); } - } - - /// - /// The position of the stream pointer. - /// - /// - /// - /// Setting this property always throws a . Reading will return the total bytes - /// written out, if used in writing, or the total bytes read in, if used in - /// reading. The count may refer to compressed bytes or uncompressed bytes, - /// depending on how you've used the stream. - /// - public override long Position - { - get - { - if (this._baseStream._streamMode == Ionic.Zlib.ZlibBaseStream.StreamMode.Writer) - return this._baseStream._z.TotalBytesOut + _headerByteCount; - if (this._baseStream._streamMode == Ionic.Zlib.ZlibBaseStream.StreamMode.Reader) - return this._baseStream._z.TotalBytesIn + this._baseStream._gzipHeaderByteCount; - return 0; - } - - set { throw new NotImplementedException(); } - } - - /// - /// Read and decompress data from the source stream. - /// - /// - /// - /// With a GZipStream, decompression is done through reading. - /// - /// - /// - /// - /// byte[] working = new byte[WORKING_BUFFER_SIZE]; - /// using (System.IO.Stream input = System.IO.File.OpenRead(_CompressedFile)) - /// { - /// using (Stream decompressor= new Ionic.Zlib.GZipStream(input, CompressionMode.Decompress, true)) - /// { - /// using (var output = System.IO.File.Create(_DecompressedFile)) - /// { - /// int n; - /// while ((n= decompressor.Read(working, 0, working.Length)) !=0) - /// { - /// output.Write(working, 0, n); - /// } - /// } - /// } - /// } - /// - /// - /// The buffer into which the decompressed data should be placed. - /// the offset within that data array to put the first byte read. - /// the number of bytes to read. - /// the number of bytes actually read - public override int Read(byte[] buffer, int offset, int count) - { - if (_disposed) throw new ObjectDisposedException("GZipStream"); - int n = _baseStream.Read(buffer, offset, count); - - // Console.WriteLine("GZipStream::Read(buffer, off({0}), c({1}) = {2}", offset, count, n); - // Console.WriteLine( Util.FormatByteArray(buffer, offset, n) ); - - if (!_firstReadDone) - { - _firstReadDone = true; - FileName = _baseStream._GzipFileName; - Comment = _baseStream._GzipComment; - } - return n; - } - - - - /// - /// Calling this method always throws a . - /// - /// irrelevant; it will always throw! - /// irrelevant; it will always throw! - /// irrelevant! - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotImplementedException(); - } - - /// - /// Calling this method always throws a . - /// - /// irrelevant; this method will always throw! - public override void SetLength(long value) - { - throw new NotImplementedException(); - } - - /// - /// Write data to the stream. - /// - /// - /// - /// - /// If you wish to use the GZipStream to compress data while writing, - /// you can create a GZipStream with CompressionMode.Compress, and a - /// writable output stream. Then call Write() on that GZipStream, - /// providing uncompressed data as input. The data sent to the output stream - /// will be the compressed form of the data written. - /// - /// - /// - /// A GZipStream can be used for Read() or Write(), but not - /// both. Writing implies compression. Reading implies decompression. - /// - /// - /// - /// The buffer holding data to write to the stream. - /// the offset within that data array to find the first byte to write. - /// the number of bytes to write. - public override void Write(byte[] buffer, int offset, int count) - { - if (_disposed) throw new ObjectDisposedException("GZipStream"); - if (_baseStream._streamMode == Ionic.Zlib.ZlibBaseStream.StreamMode.Undefined) - { - //Console.WriteLine("GZipStream: First write"); - if (_baseStream._wantCompress) - { - // first write in compression, therefore, emit the GZIP header - _headerByteCount = EmitHeader(); - } - else - { - throw new InvalidOperationException(); - } - } - - _baseStream.Write(buffer, offset, count); - } - #endregion - - - internal static readonly System.DateTime _unixEpoch = new System.DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); -#if SILVERLIGHT || NETCF - internal static readonly System.Text.Encoding iso8859dash1 = new Ionic.Encoding.Iso8859Dash1Encoding(); -#else - internal static readonly System.Text.Encoding iso8859dash1 = System.Text.Encoding.GetEncoding("iso-8859-1"); -#endif - - - private int EmitHeader() - { - byte[] commentBytes = (Comment == null) ? null : iso8859dash1.GetBytes(Comment); - byte[] filenameBytes = (FileName == null) ? null : iso8859dash1.GetBytes(FileName); - - int cbLength = (Comment == null) ? 0 : commentBytes.Length + 1; - int fnLength = (FileName == null) ? 0 : filenameBytes.Length + 1; - - int bufferLength = 10 + cbLength + fnLength; - byte[] header = new byte[bufferLength]; - int i = 0; - // ID - header[i++] = 0x1F; - header[i++] = 0x8B; - - // compression method - header[i++] = 8; - byte flag = 0; - if (Comment != null) - flag ^= 0x10; - if (FileName != null) - flag ^= 0x8; - - // flag - header[i++] = flag; - - // mtime - if (!LastModified.HasValue) LastModified = DateTime.Now; - System.TimeSpan delta = LastModified.Value - _unixEpoch; - Int32 timet = (Int32)delta.TotalSeconds; - Array.Copy(BitConverter.GetBytes(timet), 0, header, i, 4); - i += 4; - - // xflg - header[i++] = 0; // this field is totally useless - // OS - header[i++] = 0xFF; // 0xFF == unspecified - - // extra field length - only if FEXTRA is set, which it is not. - //header[i++]= 0; - //header[i++]= 0; - - // filename - if (fnLength != 0) - { - Array.Copy(filenameBytes, 0, header, i, fnLength - 1); - i += fnLength - 1; - header[i++] = 0; // terminate - } - - // comment - if (cbLength != 0) - { - Array.Copy(commentBytes, 0, header, i, cbLength - 1); - i += cbLength - 1; - header[i++] = 0; // terminate - } - - _baseStream._stream.Write(header, 0, header.Length); - - return header.Length; // bytes written - } - - - - /// - /// Compress a string into a byte array using GZip. - /// - /// - /// - /// Uncompress it with . - /// - /// - /// - /// - /// - /// - /// A string to compress. The string will first be encoded - /// using UTF8, then compressed. - /// - /// - /// The string in compressed form - public static byte[] CompressString(String s) - { - using (var ms = new MemoryStream()) - { - System.IO.Stream compressor = - new GZipStream(ms, CompressionMode.Compress, CompressionLevel.BestCompression); - ZlibBaseStream.CompressString(s, compressor); - return ms.ToArray(); - } - } - - - /// - /// Compress a byte array into a new byte array using GZip. - /// - /// - /// - /// Uncompress it with . - /// - /// - /// - /// - /// - /// - /// A buffer to compress. - /// - /// - /// The data in compressed form - public static byte[] CompressBuffer(byte[] b) - { - using (var ms = new MemoryStream()) - { - System.IO.Stream compressor = - new GZipStream( ms, CompressionMode.Compress, CompressionLevel.BestCompression ); - - ZlibBaseStream.CompressBuffer(b, compressor); - return ms.ToArray(); - } - } - - - /// - /// Uncompress a GZip'ed byte array into a single string. - /// - /// - /// - /// - /// - /// - /// A buffer containing GZIP-compressed data. - /// - /// - /// The uncompressed string - public static String UncompressString(byte[] compressed) - { - using (var input = new MemoryStream(compressed)) - { - Stream decompressor = new GZipStream(input, CompressionMode.Decompress); - return ZlibBaseStream.UncompressString(compressed, decompressor); - } - } - - - /// - /// Uncompress a GZip'ed byte array into a byte array. - /// - /// - /// - /// - /// - /// - /// A buffer containing data that has been compressed with GZip. - /// - /// - /// The data in uncompressed form - public static byte[] UncompressBuffer(byte[] compressed) - { - using (var input = new System.IO.MemoryStream(compressed)) - { - System.IO.Stream decompressor = - new GZipStream( input, CompressionMode.Decompress ); - - return ZlibBaseStream.UncompressBuffer(compressed, decompressor); - } - } - - - } -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/InfTree.cs b/MinecraftClient/Protocol/Handlers/Compression/InfTree.cs deleted file mode 100644 index 416b143a..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/InfTree.cs +++ /dev/null @@ -1,436 +0,0 @@ -// Inftree.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation. -// 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: <2009-October-28 12:43:54> -// -// ------------------------------------------------------------------ -// -// This module defines classes used in decompression. This code is derived -// from the jzlib implementation of zlib. In keeping with the license for jzlib, -// the copyright to that code is below. -// -// ------------------------------------------------------------------ -// -// Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in -// the documentation and/or other materials provided with the distribution. -// -// 3. The names of the authors may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -// INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// ----------------------------------------------------------------------- -// -// This program is based on zlib-1.1.3; credit to authors -// Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) -// and contributors of zlib. -// -// ----------------------------------------------------------------------- - - - -using System; -namespace Ionic.Zlib -{ - - sealed class InfTree - { - - private const int MANY = 1440; - - private const int Z_OK = 0; - private const int Z_STREAM_END = 1; - private const int Z_NEED_DICT = 2; - private const int Z_ERRNO = - 1; - private const int Z_STREAM_ERROR = - 2; - private const int Z_DATA_ERROR = - 3; - private const int Z_MEM_ERROR = - 4; - private const int Z_BUF_ERROR = - 5; - private const int Z_VERSION_ERROR = - 6; - - internal const int fixed_bl = 9; - internal const int fixed_bd = 5; - - //UPGRADE_NOTE: Final was removed from the declaration of 'fixed_tl'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - internal static readonly int[] fixed_tl = new int[]{96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115, 82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9, 192, 80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 160, 0, 8, 0, 0, 8, 128, 0, 8, 64, 0, 9, 224, 80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 144, 83, 7, 59, 0, 8, 120, 0, 8, 56, 0, 9, 208, 81, 7, 17, 0, 8, 104, 0, 8, 40, 0, 9, 176, 0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 240, 80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8, 227, 83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 200, 81, 7, 13, 0, 8, 100, 0, 8, 36, 0, 9, 168, 0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 232, 80, 7, 8, 0, 8, 92, 0, 8, 28, 0, 9, 152, 84, 7, 83, 0, 8, 124, 0, 8, 60, 0, 9, 216, 82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 184, 0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9, 248, 80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163, 83, 7, 35, 0, 8, 114, 0, 8, 50, 0, 9, 196, 81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 164, 0, 8, 2, 0, 8, 130, 0, 8, 66, 0, 9, 228, 80, 7, 7, 0, 8, 90, 0, 8, 26, 0, 9, 148, 84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 212, 82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9, 180, 0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 244, 80, 7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0, 83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 204, 81, 7, 15, 0, 8, 102, 0, 8, 38, 0, 9, 172, 0, 8, 6, 0, 8, 134, 0, 8, 70, 0, 9, 236, 80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 156, 84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9, 220, 82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 188, 0, 8, 14, 0, 8, 142, 0, 8, 78, 0, 9, 252, 96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131, 82, 7, 31, 0, 8, 113, 0, 8, 49, 0, 9, 194, 80, 7, 10, 0, 8, 97, 0, 8, 33, 0, 9, 162, 0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 226, 80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9, 146, 83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 210, 81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 178, 0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 242, 80, 7, 4, 0, 8, 85, 0, 8, 21, 80, 8, 258, 83, 7, 43, 0, 8, 117, 0, 8, 53, 0, 9, 202, 81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 170, 0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9, 234, 80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 154, 84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 218, 82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 186, - 0, 8, 13, 0, 8, 141, 0, 8, 77, 0, 9, 250, 80, 7, 3, 0, 8, 83, 0, 8, 19, 85, 8, 195, 83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 198, 81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9, 166, 0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 230, 80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 150, 84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 214, 82, 7, 19, 0, 8, 107, 0, 8, 43, 0, 9, 182, 0, 8, 11, 0, 8, 139, 0, 8, 75, 0, 9, 246, 80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0, 83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9, 206, 81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 174, 0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 238, 80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 158, 84, 7, 99, 0, 8, 127, 0, 8, 63, 0, 9, 222, 82, 7, 27, 0, 8, 111, 0, 8, 47, 0, 9, 190, 0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 254, 96, 7, 256, 0, 8, 80, 0, 8, 16, 84, 8, 115, 82, 7, 31, 0, 8, 112, 0, 8, 48, 0, 9, 193, 80, 7, 10, 0, 8, 96, 0, 8, 32, 0, 9, 161, 0, 8, 0, 0, 8, 128, 0, 8, 64, 0, 9, 225, 80, 7, 6, 0, 8, 88, 0, 8, 24, 0, 9, 145, 83, 7, 59, 0, 8, 120, 0, 8, 56, 0, 9, 209, 81, 7, 17, 0, 8, 104, 0, 8, 40, 0, 9, 177, 0, 8, 8, 0, 8, 136, 0, 8, 72, 0, 9, 241, 80, 7, 4, 0, 8, 84, 0, 8, 20, 85, 8, 227, 83, 7, 43, 0, 8, 116, 0, 8, 52, 0, 9, 201, 81, 7, 13, 0, 8, 100, 0, 8, 36, 0, 9, 169, 0, 8, 4, 0, 8, 132, 0, 8, 68, 0, 9, 233, 80, 7, 8, 0, 8, 92, 0, 8, 28, 0, 9, 153, 84, 7, 83, 0, 8, 124, 0, 8, 60, 0, 9, 217, 82, 7, 23, 0, 8, 108, 0, 8, 44, 0, 9, 185, 0, 8, 12, 0, 8, 140, 0, 8, 76, 0, 9, 249, 80, 7, 3, 0, 8, 82, 0, 8, 18, 85, 8, 163, 83, 7, 35, 0, 8, 114, 0, 8, 50, 0, 9, 197, 81, 7, 11, 0, 8, 98, 0, 8, 34, 0, 9, 165, 0, 8, 2, 0, 8, 130, 0, 8, 66, 0, 9, 229, 80, 7, 7, 0, 8, 90, 0, 8, 26, 0, 9, 149, 84, 7, 67, 0, 8, 122, 0, 8, 58, 0, 9, 213, 82, 7, 19, 0, 8, 106, 0, 8, 42, 0, 9, 181, 0, 8, 10, 0, 8, 138, 0, 8, 74, 0, 9, 245, 80, 7, 5, 0, 8, 86, 0, 8, 22, 192, 8, 0, 83, 7, 51, 0, 8, 118, 0, 8, 54, 0, 9, 205, 81, 7, 15, 0, 8, 102, 0, 8, 38, 0, 9, 173, 0, 8, 6, 0, 8, 134, 0, 8, 70, 0, 9, 237, 80, 7, 9, 0, 8, 94, 0, 8, 30, 0, 9, 157, 84, 7, 99, 0, 8, 126, 0, 8, 62, 0, 9, 221, 82, 7, 27, 0, 8, 110, 0, 8, 46, 0, 9, 189, 0, 8, - 14, 0, 8, 142, 0, 8, 78, 0, 9, 253, 96, 7, 256, 0, 8, 81, 0, 8, 17, 85, 8, 131, 82, 7, 31, 0, 8, 113, 0, 8, 49, 0, 9, 195, 80, 7, 10, 0, 8, 97, 0, 8, 33, 0, 9, 163, 0, 8, 1, 0, 8, 129, 0, 8, 65, 0, 9, 227, 80, 7, 6, 0, 8, 89, 0, 8, 25, 0, 9, 147, 83, 7, 59, 0, 8, 121, 0, 8, 57, 0, 9, 211, 81, 7, 17, 0, 8, 105, 0, 8, 41, 0, 9, 179, 0, 8, 9, 0, 8, 137, 0, 8, 73, 0, 9, 243, 80, 7, 4, 0, 8, 85, 0, 8, 21, 80, 8, 258, 83, 7, 43, 0, 8, 117, 0, 8, 53, 0, 9, 203, 81, 7, 13, 0, 8, 101, 0, 8, 37, 0, 9, 171, 0, 8, 5, 0, 8, 133, 0, 8, 69, 0, 9, 235, 80, 7, 8, 0, 8, 93, 0, 8, 29, 0, 9, 155, 84, 7, 83, 0, 8, 125, 0, 8, 61, 0, 9, 219, 82, 7, 23, 0, 8, 109, 0, 8, 45, 0, 9, 187, 0, 8, 13, 0, 8, 141, 0, 8, 77, 0, 9, 251, 80, 7, 3, 0, 8, 83, 0, 8, 19, 85, 8, 195, 83, 7, 35, 0, 8, 115, 0, 8, 51, 0, 9, 199, 81, 7, 11, 0, 8, 99, 0, 8, 35, 0, 9, 167, 0, 8, 3, 0, 8, 131, 0, 8, 67, 0, 9, 231, 80, 7, 7, 0, 8, 91, 0, 8, 27, 0, 9, 151, 84, 7, 67, 0, 8, 123, 0, 8, 59, 0, 9, 215, 82, 7, 19, 0, 8, 107, 0, 8, 43, 0, 9, 183, 0, 8, 11, 0, 8, 139, 0, 8, 75, 0, 9, 247, 80, 7, 5, 0, 8, 87, 0, 8, 23, 192, 8, 0, 83, 7, 51, 0, 8, 119, 0, 8, 55, 0, 9, 207, 81, 7, 15, 0, 8, 103, 0, 8, 39, 0, 9, 175, 0, 8, 7, 0, 8, 135, 0, 8, 71, 0, 9, 239, 80, 7, 9, 0, 8, 95, 0, 8, 31, 0, 9, 159, 84, 7, 99, 0, 8, 127, 0, 8, 63, 0, 9, 223, 82, 7, 27, 0, 8, 111, 0, 8, 47, 0, 9, 191, 0, 8, 15, 0, 8, 143, 0, 8, 79, 0, 9, 255}; - //UPGRADE_NOTE: Final was removed from the declaration of 'fixed_td'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - internal static readonly int[] fixed_td = new int[]{80, 5, 1, 87, 5, 257, 83, 5, 17, 91, 5, 4097, 81, 5, 5, 89, 5, 1025, 85, 5, 65, 93, 5, 16385, 80, 5, 3, 88, 5, 513, 84, 5, 33, 92, 5, 8193, 82, 5, 9, 90, 5, 2049, 86, 5, 129, 192, 5, 24577, 80, 5, 2, 87, 5, 385, 83, 5, 25, 91, 5, 6145, 81, 5, 7, 89, 5, 1537, 85, 5, 97, 93, 5, 24577, 80, 5, 4, 88, 5, 769, 84, 5, 49, 92, 5, 12289, 82, 5, 13, 90, 5, 3073, 86, 5, 193, 192, 5, 24577}; - - // Tables for deflate from PKZIP's appnote.txt. - //UPGRADE_NOTE: Final was removed from the declaration of 'cplens'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - internal static readonly int[] cplens = new int[]{3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; - - // see note #13 above about 258 - //UPGRADE_NOTE: Final was removed from the declaration of 'cplext'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - internal static readonly int[] cplext = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; - - //UPGRADE_NOTE: Final was removed from the declaration of 'cpdist'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - internal static readonly int[] cpdist = new int[]{1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577}; - - //UPGRADE_NOTE: Final was removed from the declaration of 'cpdext'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'" - internal static readonly int[] cpdext = new int[]{0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; - - // If BMAX needs to be larger than 16, then h and x[] should be uLong. - internal const int BMAX = 15; // maximum bit length of any code - - internal int[] hn = null; // hufts used in space - internal int[] v = null; // work area for huft_build - internal int[] c = null; // bit length count table - internal int[] r = null; // table entry for structure assignment - internal int[] u = null; // table stack - internal int[] x = null; // bit offsets, then code stack - - private int huft_build(int[] b, int bindex, int n, int s, int[] d, int[] e, int[] t, int[] m, int[] hp, int[] hn, int[] v) - { - // Given a list of code lengths and a maximum table size, make a set of - // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR - // if the given code set is incomplete (the tables are still built in this - // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of - // lengths), or Z_MEM_ERROR if not enough memory. - - int a; // counter for codes of length k - int f; // i repeats in table every f entries - int g; // maximum code length - int h; // table level - int i; // counter, current code - int j; // counter - int k; // number of bits in current code - int l; // bits per table (returned in m) - int mask; // (1 << w) - 1, to avoid cc -O bug on HP - int p; // pointer into c[], b[], or v[] - int q; // points to current table - int w; // bits before this table == (l * h) - int xp; // pointer into x - int y; // number of dummy codes added - int z; // number of entries in current table - - // Generate counts for each bit length - - p = 0; i = n; - do - { - c[b[bindex + p]]++; p++; i--; // assume all entries <= BMAX - } - while (i != 0); - - if (c[0] == n) - { - // null input--all zero length codes - t[0] = - 1; - m[0] = 0; - return Z_OK; - } - - // Find minimum and maximum length, bound *m by those - l = m[0]; - for (j = 1; j <= BMAX; j++) - if (c[j] != 0) - break; - k = j; // minimum code length - if (l < j) - { - l = j; - } - for (i = BMAX; i != 0; i--) - { - if (c[i] != 0) - break; - } - g = i; // maximum code length - if (l > i) - { - l = i; - } - m[0] = l; - - // Adjust last length count to fill out codes, if needed - for (y = 1 << j; j < i; j++, y <<= 1) - { - if ((y -= c[j]) < 0) - { - return Z_DATA_ERROR; - } - } - if ((y -= c[i]) < 0) - { - return Z_DATA_ERROR; - } - c[i] += y; - - // Generate starting offsets into the value table for each length - x[1] = j = 0; - p = 1; xp = 2; - while (--i != 0) - { - // note that i == g from above - x[xp] = (j += c[p]); - xp++; - p++; - } - - // Make a table of values in order of bit lengths - i = 0; p = 0; - do - { - if ((j = b[bindex + p]) != 0) - { - v[x[j]++] = i; - } - p++; - } - while (++i < n); - n = x[g]; // set n to length of v - - // Generate the Huffman codes and for each, make the table entries - x[0] = i = 0; // first Huffman code is zero - p = 0; // grab values in bit order - h = - 1; // no tables yet--level -1 - w = - l; // bits decoded == (l * h) - u[0] = 0; // just to keep compilers happy - q = 0; // ditto - z = 0; // ditto - - // go through the bit lengths (k already is bits in shortest code) - for (; k <= g; k++) - { - a = c[k]; - while (a-- != 0) - { - // here i is the Huffman code of length k bits for value *p - // make tables up to required level - while (k > w + l) - { - h++; - w += l; // previous table always l bits - // compute minimum size table less than or equal to l bits - z = g - w; - z = (z > l)?l:z; // table size upper limit - if ((f = 1 << (j = k - w)) > a + 1) - { - // try a k-w bit table - // too few codes for k-w bit table - f -= (a + 1); // deduct codes from patterns left - xp = k; - if (j < z) - { - while (++j < z) - { - // try smaller tables up to z bits - if ((f <<= 1) <= c[++xp]) - break; // enough codes to use up j bits - f -= c[xp]; // else deduct codes from patterns - } - } - } - z = 1 << j; // table entries for j-bit table - - // allocate new table - if (hn[0] + z > MANY) - { - // (note: doesn't matter for fixed) - return Z_DATA_ERROR; // overflow of MANY - } - u[h] = q = hn[0]; // DEBUG - hn[0] += z; - - // connect to last table, if there is one - if (h != 0) - { - x[h] = i; // save pattern for backing up - r[0] = (sbyte) j; // bits in this table - r[1] = (sbyte) l; // bits to dump before this table - j = SharedUtils.URShift(i, (w - l)); - r[2] = (int) (q - u[h - 1] - j); // offset to this table - Array.Copy(r, 0, hp, (u[h - 1] + j) * 3, 3); // connect to last table - } - else - { - t[0] = q; // first table is returned result - } - } - - // set up table entry in r - r[1] = (sbyte) (k - w); - if (p >= n) - { - r[0] = 128 + 64; // out of values--invalid code - } - else if (v[p] < s) - { - r[0] = (sbyte) (v[p] < 256?0:32 + 64); // 256 is end-of-block - r[2] = v[p++]; // simple code is just the value - } - else - { - r[0] = (sbyte) (e[v[p] - s] + 16 + 64); // non-simple--look up in lists - r[2] = d[v[p++] - s]; - } - - // fill code-like entries with r - f = 1 << (k - w); - for (j = SharedUtils.URShift(i, w); j < z; j += f) - { - Array.Copy(r, 0, hp, (q + j) * 3, 3); - } - - // backwards increment the k-bit code i - for (j = 1 << (k - 1); (i & j) != 0; j = SharedUtils.URShift(j, 1)) - { - i ^= j; - } - i ^= j; - - // backup over finished tables - mask = (1 << w) - 1; // needed on HP, cc -O bug - while ((i & mask) != x[h]) - { - h--; // don't need to update q - w -= l; - mask = (1 << w) - 1; - } - } - } - // Return Z_BUF_ERROR if we were given an incomplete table - return y != 0 && g != 1?Z_BUF_ERROR:Z_OK; - } - - internal int inflate_trees_bits(int[] c, int[] bb, int[] tb, int[] hp, ZlibCodec z) - { - int result; - initWorkArea(19); - hn[0] = 0; - result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v); - - if (result == Z_DATA_ERROR) - { - z.Message = "oversubscribed dynamic bit lengths tree"; - } - else if (result == Z_BUF_ERROR || bb[0] == 0) - { - z.Message = "incomplete dynamic bit lengths tree"; - result = Z_DATA_ERROR; - } - return result; - } - - internal int inflate_trees_dynamic(int nl, int nd, int[] c, int[] bl, int[] bd, int[] tl, int[] td, int[] hp, ZlibCodec z) - { - int result; - - // build literal/length tree - initWorkArea(288); - hn[0] = 0; - result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v); - if (result != Z_OK || bl[0] == 0) - { - if (result == Z_DATA_ERROR) - { - z.Message = "oversubscribed literal/length tree"; - } - else if (result != Z_MEM_ERROR) - { - z.Message = "incomplete literal/length tree"; - result = Z_DATA_ERROR; - } - return result; - } - - // build distance tree - initWorkArea(288); - result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v); - - if (result != Z_OK || (bd[0] == 0 && nl > 257)) - { - if (result == Z_DATA_ERROR) - { - z.Message = "oversubscribed distance tree"; - } - else if (result == Z_BUF_ERROR) - { - z.Message = "incomplete distance tree"; - result = Z_DATA_ERROR; - } - else if (result != Z_MEM_ERROR) - { - z.Message = "empty distance tree with lengths"; - result = Z_DATA_ERROR; - } - return result; - } - - return Z_OK; - } - - internal static int inflate_trees_fixed(int[] bl, int[] bd, int[][] tl, int[][] td, ZlibCodec z) - { - bl[0] = fixed_bl; - bd[0] = fixed_bd; - tl[0] = fixed_tl; - td[0] = fixed_td; - return Z_OK; - } - - private void initWorkArea(int vsize) - { - if (hn == null) - { - hn = new int[1]; - v = new int[vsize]; - c = new int[BMAX + 1]; - r = new int[3]; - u = new int[BMAX]; - x = new int[BMAX + 1]; - } - else - { - if (v.Length < vsize) - { - v = new int[vsize]; - } - Array.Clear(v,0,vsize); - Array.Clear(c,0,BMAX+1); - r[0]=0; r[1]=0; r[2]=0; - // for(int i=0; i -// -// ------------------------------------------------------------------ -// -// This module defines classes for decompression. This code is derived -// from the jzlib implementation of zlib, but significantly modified. -// The object model is not the same, and many of the behaviors are -// different. Nonetheless, in keeping with the license for jzlib, I am -// reproducing the copyright to that code here. -// -// ------------------------------------------------------------------ -// -// Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in -// the documentation and/or other materials provided with the distribution. -// -// 3. The names of the authors may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -// INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// ----------------------------------------------------------------------- -// -// This program is based on zlib-1.1.3; credit to authors -// Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) -// and contributors of zlib. -// -// ----------------------------------------------------------------------- - - -using System; -using System.Runtime.CompilerServices; - -namespace Ionic.Zlib -{ - sealed class InflateBlocks - { - private const int MANY = 1440; - - // Table for deflate from PKZIP's appnote.txt. - internal static readonly int[] border = new int[] { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; - - private enum InflateBlockMode - { - TYPE = 0, // get type bits (3, including end bit) - LENS = 1, // get lengths for stored - STORED = 2, // processing stored block - TABLE = 3, // get table lengths - BTREE = 4, // get bit lengths tree for a dynamic block - DTREE = 5, // get length, distance trees for a dynamic block - CODES = 6, // processing fixed or dynamic block - DRY = 7, // output remaining window bytes - DONE = 8, // finished last block, done - BAD = 9, // ot a data error--stuck here - } - - private InflateBlockMode mode; // current inflate_block mode - - internal int left; // if STORED, bytes left to copy - - internal int table; // table lengths (14 bits) - internal int index; // index into blens (or border) - internal int[] blens; // bit lengths of codes - internal int[] bb = new int[1]; // bit length tree depth - internal int[] tb = new int[1]; // bit length decoding tree - - internal InflateCodes codes = new InflateCodes(); // if CODES, current state - - internal int last; // true if this block is the last block - - internal ZlibCodec _codec; // pointer back to this zlib stream - - // mode independent information - internal int bitk; // bits in bit buffer - internal int bitb; // bit buffer - internal int[] hufts; // single malloc for tree space - internal byte[] window; // sliding window - internal int end; // one byte after sliding window - internal int readAt; // window read pointer - internal int writeAt; // window write pointer - internal System.Object checkfn; // check function - internal uint check; // check on output - - internal InfTree inftree = new InfTree(); - - internal InflateBlocks(ZlibCodec codec, System.Object checkfn, int w) - { - _codec = codec; - hufts = new int[MANY * 3]; - window = new byte[w]; - end = w; - this.checkfn = checkfn; - mode = InflateBlockMode.TYPE; - Reset(); - } - - internal uint Reset() - { - uint oldCheck = check; - mode = InflateBlockMode.TYPE; - bitk = 0; - bitb = 0; - readAt = writeAt = 0; - - if (checkfn != null) - _codec._Adler32 = check = Adler.Adler32(0, null, 0, 0); - return oldCheck; - } - - internal int Process(int r) - { - int t; // temporary storage - int b; // bit buffer - int k; // bits in bit buffer - int p; // input data pointer - int n; // bytes available there - int q; // output window write pointer - int m; // bytes to end of window or read pointer - - // copy input/output information to locals (UPDATE macro restores) - - p = _codec.NextIn; - n = _codec.AvailableBytesIn; - b = bitb; - k = bitk; - - q = writeAt; - m = (int)(q < readAt ? readAt - q - 1 : end - q); - - - // process input based on current state - while (true) - { - switch (mode) - { - case InflateBlockMode.TYPE: - - while (k < (3)) - { - if (n != 0) - { - r = ZlibConstants.Z_OK; - } - else - { - bitb = b; bitk = k; - _codec.AvailableBytesIn = n; - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - writeAt = q; - return Flush(r); - } - - n--; - b |= (_codec.InputBuffer[p++] & 0xff) << k; - k += 8; - } - t = (int)(b & 7); - last = t & 1; - - switch ((uint)t >> 1) - { - case 0: // stored - b >>= 3; k -= (3); - t = k & 7; // go to byte boundary - b >>= t; k -= t; - mode = InflateBlockMode.LENS; // get length of stored block - break; - - case 1: // fixed - int[] bl = new int[1]; - int[] bd = new int[1]; - int[][] tl = new int[1][]; - int[][] td = new int[1][]; - InfTree.inflate_trees_fixed(bl, bd, tl, td, _codec); - codes.Init(bl[0], bd[0], tl[0], 0, td[0], 0); - b >>= 3; k -= 3; - mode = InflateBlockMode.CODES; - break; - - case 2: // dynamic - b >>= 3; k -= 3; - mode = InflateBlockMode.TABLE; - break; - - case 3: // illegal - b >>= 3; k -= 3; - mode = InflateBlockMode.BAD; - _codec.Message = "invalid block type"; - r = ZlibConstants.Z_DATA_ERROR; - bitb = b; bitk = k; - _codec.AvailableBytesIn = n; - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - writeAt = q; - return Flush(r); - } - break; - - case InflateBlockMode.LENS: - - while (k < (32)) - { - if (n != 0) - { - r = ZlibConstants.Z_OK; - } - else - { - bitb = b; bitk = k; - _codec.AvailableBytesIn = n; - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - writeAt = q; - return Flush(r); - } - ; - n--; - b |= (_codec.InputBuffer[p++] & 0xff) << k; - k += 8; - } - - if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) - { - mode = InflateBlockMode.BAD; - _codec.Message = "invalid stored block lengths"; - r = ZlibConstants.Z_DATA_ERROR; - - bitb = b; bitk = k; - _codec.AvailableBytesIn = n; - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - writeAt = q; - return Flush(r); - } - left = (b & 0xffff); - b = k = 0; // dump bits - mode = left != 0 ? InflateBlockMode.STORED : (last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE); - break; - - case InflateBlockMode.STORED: - if (n == 0) - { - bitb = b; bitk = k; - _codec.AvailableBytesIn = n; - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - writeAt = q; - return Flush(r); - } - - if (m == 0) - { - if (q == end && readAt != 0) - { - q = 0; m = (int)(q < readAt ? readAt - q - 1 : end - q); - } - if (m == 0) - { - writeAt = q; - r = Flush(r); - q = writeAt; m = (int)(q < readAt ? readAt - q - 1 : end - q); - if (q == end && readAt != 0) - { - q = 0; m = (int)(q < readAt ? readAt - q - 1 : end - q); - } - if (m == 0) - { - bitb = b; bitk = k; - _codec.AvailableBytesIn = n; - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - writeAt = q; - return Flush(r); - } - } - } - r = ZlibConstants.Z_OK; - - t = left; - if (t > n) - t = n; - if (t > m) - t = m; - Array.Copy(_codec.InputBuffer, p, window, q, t); - p += t; n -= t; - q += t; m -= t; - if ((left -= t) != 0) - break; - mode = last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE; - break; - - case InflateBlockMode.TABLE: - - while (k < (14)) - { - if (n != 0) - { - r = ZlibConstants.Z_OK; - } - else - { - bitb = b; bitk = k; - _codec.AvailableBytesIn = n; - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - writeAt = q; - return Flush(r); - } - - n--; - b |= (_codec.InputBuffer[p++] & 0xff) << k; - k += 8; - } - - table = t = (b & 0x3fff); - if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) - { - mode = InflateBlockMode.BAD; - _codec.Message = "too many length or distance symbols"; - r = ZlibConstants.Z_DATA_ERROR; - - bitb = b; bitk = k; - _codec.AvailableBytesIn = n; - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - writeAt = q; - return Flush(r); - } - t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); - if (blens == null || blens.Length < t) - { - blens = new int[t]; - } - else - { - Array.Clear(blens, 0, t); - // for (int i = 0; i < t; i++) - // { - // blens[i] = 0; - // } - } - - b >>= 14; - k -= 14; - - - index = 0; - mode = InflateBlockMode.BTREE; - goto case InflateBlockMode.BTREE; - - case InflateBlockMode.BTREE: - while (index < 4 + (table >> 10)) - { - while (k < (3)) - { - if (n != 0) - { - r = ZlibConstants.Z_OK; - } - else - { - bitb = b; bitk = k; - _codec.AvailableBytesIn = n; - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - writeAt = q; - return Flush(r); - } - - n--; - b |= (_codec.InputBuffer[p++] & 0xff) << k; - k += 8; - } - - blens[border[index++]] = b & 7; - - b >>= 3; k -= 3; - } - - while (index < 19) - { - blens[border[index++]] = 0; - } - - bb[0] = 7; - t = inftree.inflate_trees_bits(blens, bb, tb, hufts, _codec); - if (t != ZlibConstants.Z_OK) - { - r = t; - if (r == ZlibConstants.Z_DATA_ERROR) - { - blens = null; - mode = InflateBlockMode.BAD; - } - - bitb = b; bitk = k; - _codec.AvailableBytesIn = n; - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - writeAt = q; - return Flush(r); - } - - index = 0; - mode = InflateBlockMode.DTREE; - goto case InflateBlockMode.DTREE; - - case InflateBlockMode.DTREE: - while (true) - { - t = table; - if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))) - { - break; - } - - int i, j, c; - - t = bb[0]; - - while (k < t) - { - if (n != 0) - { - r = ZlibConstants.Z_OK; - } - else - { - bitb = b; bitk = k; - _codec.AvailableBytesIn = n; - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - writeAt = q; - return Flush(r); - } - - n--; - b |= (_codec.InputBuffer[p++] & 0xff) << k; - k += 8; - } - - t = hufts[(tb[0] + (b & InternalInflateConstants.InflateMask[t])) * 3 + 1]; - c = hufts[(tb[0] + (b & InternalInflateConstants.InflateMask[t])) * 3 + 2]; - - if (c < 16) - { - b >>= t; k -= t; - blens[index++] = c; - } - else - { - // c == 16..18 - i = c == 18 ? 7 : c - 14; - j = c == 18 ? 11 : 3; - - while (k < (t + i)) - { - if (n != 0) - { - r = ZlibConstants.Z_OK; - } - else - { - bitb = b; bitk = k; - _codec.AvailableBytesIn = n; - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - writeAt = q; - return Flush(r); - } - - n--; - b |= (_codec.InputBuffer[p++] & 0xff) << k; - k += 8; - } - - b >>= t; k -= t; - - j += (b & InternalInflateConstants.InflateMask[i]); - - b >>= i; k -= i; - - i = index; - t = table; - if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || (c == 16 && i < 1)) - { - blens = null; - mode = InflateBlockMode.BAD; - _codec.Message = "invalid bit length repeat"; - r = ZlibConstants.Z_DATA_ERROR; - - bitb = b; bitk = k; - _codec.AvailableBytesIn = n; - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - writeAt = q; - return Flush(r); - } - - c = (c == 16) ? blens[i - 1] : 0; - do - { - blens[i++] = c; - } - while (--j != 0); - index = i; - } - } - - tb[0] = -1; - { - int[] bl = new int[] { 9 }; // must be <= 9 for lookahead assumptions - int[] bd = new int[] { 6 }; // must be <= 9 for lookahead assumptions - int[] tl = new int[1]; - int[] td = new int[1]; - - t = table; - t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), blens, bl, bd, tl, td, hufts, _codec); - - if (t != ZlibConstants.Z_OK) - { - if (t == ZlibConstants.Z_DATA_ERROR) - { - blens = null; - mode = InflateBlockMode.BAD; - } - r = t; - - bitb = b; bitk = k; - _codec.AvailableBytesIn = n; - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - writeAt = q; - return Flush(r); - } - codes.Init(bl[0], bd[0], hufts, tl[0], hufts, td[0]); - } - mode = InflateBlockMode.CODES; - goto case InflateBlockMode.CODES; - - case InflateBlockMode.CODES: - bitb = b; bitk = k; - _codec.AvailableBytesIn = n; - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - writeAt = q; - - r = codes.Process(this, r); - if (r != ZlibConstants.Z_STREAM_END) - { - return Flush(r); - } - - r = ZlibConstants.Z_OK; - p = _codec.NextIn; - n = _codec.AvailableBytesIn; - b = bitb; - k = bitk; - q = writeAt; - m = (int)(q < readAt ? readAt - q - 1 : end - q); - - if (last == 0) - { - mode = InflateBlockMode.TYPE; - break; - } - mode = InflateBlockMode.DRY; - goto case InflateBlockMode.DRY; - - case InflateBlockMode.DRY: - writeAt = q; - r = Flush(r); - q = writeAt; m = (int)(q < readAt ? readAt - q - 1 : end - q); - if (readAt != writeAt) - { - bitb = b; bitk = k; - _codec.AvailableBytesIn = n; - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - writeAt = q; - return Flush(r); - } - mode = InflateBlockMode.DONE; - goto case InflateBlockMode.DONE; - - case InflateBlockMode.DONE: - r = ZlibConstants.Z_STREAM_END; - bitb = b; - bitk = k; - _codec.AvailableBytesIn = n; - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - writeAt = q; - return Flush(r); - - case InflateBlockMode.BAD: - r = ZlibConstants.Z_DATA_ERROR; - - bitb = b; bitk = k; - _codec.AvailableBytesIn = n; - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - writeAt = q; - return Flush(r); - - - default: - r = ZlibConstants.Z_STREAM_ERROR; - - bitb = b; bitk = k; - _codec.AvailableBytesIn = n; - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - writeAt = q; - return Flush(r); - } - } - } - - - internal void Free() - { - Reset(); - window = null; - hufts = null; - } - - internal void SetDictionary(byte[] d, int start, int n) - { - Array.Copy(d, start, window, 0, n); - readAt = writeAt = n; - } - - // Returns true if inflate is currently at the end of a block generated - // by Z_SYNC_FLUSH or Z_FULL_FLUSH. - internal int SyncPoint() - { - return mode == InflateBlockMode.LENS ? 1 : 0; - } - - // copy as much as possible from the sliding window to the output area - internal int Flush(int r) - { - int nBytes; - - for (int pass = 0; pass < 2; pass++) - { - if (pass == 0) - { - // compute number of bytes to copy as far as end of window - nBytes = (int)((readAt <= writeAt ? writeAt : end) - readAt); - } - else - { - // compute bytes to copy - nBytes = writeAt - readAt; - } - - // workitem 8870 - if (nBytes == 0) - { - if (r == ZlibConstants.Z_BUF_ERROR) - r = ZlibConstants.Z_OK; - return r; - } - - if (nBytes > _codec.AvailableBytesOut) - nBytes = _codec.AvailableBytesOut; - - if (nBytes != 0 && r == ZlibConstants.Z_BUF_ERROR) - r = ZlibConstants.Z_OK; - - // update counters - _codec.AvailableBytesOut -= nBytes; - _codec.TotalBytesOut += nBytes; - - // update check information - if (checkfn != null) - _codec._Adler32 = check = Adler.Adler32(check, window, readAt, nBytes); - - // copy as far as end of window - Array.Copy(window, readAt, _codec.OutputBuffer, _codec.NextOut, nBytes); - _codec.NextOut += nBytes; - readAt += nBytes; - - // see if more to copy at beginning of window - if (readAt == end && pass == 0) - { - // wrap pointers - readAt = 0; - if (writeAt == end) - writeAt = 0; - } - else pass++; - } - - // done - return r; - } - } - - - internal static class InternalInflateConstants - { - // And'ing with mask[n] masks the lower n bits - internal static readonly int[] InflateMask = new int[] { - 0x00000000, 0x00000001, 0x00000003, 0x00000007, - 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, - 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, - 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff }; - } - - - sealed class InflateCodes - { - // waiting for "i:"=input, - // "o:"=output, - // "x:"=nothing - private const int START = 0; // x: set up for LEN - private const int LEN = 1; // i: get length/literal/eob next - private const int LENEXT = 2; // i: getting length extra (have base) - private const int DIST = 3; // i: get distance next - private const int DISTEXT = 4; // i: getting distance extra - private const int COPY = 5; // o: copying bytes in window, waiting for space - private const int LIT = 6; // o: got literal, waiting for output space - private const int WASH = 7; // o: got eob, possibly still output waiting - private const int END = 8; // x: got eob and all data flushed - private const int BADCODE = 9; // x: got error - - internal int mode; // current inflate_codes mode - - // mode dependent information - internal int len; - - internal int[] tree; // pointer into tree - internal int tree_index = 0; - internal int need; // bits needed - - internal int lit; - - // if EXT or COPY, where and how much - internal int bitsToGet; // bits to get for extra - internal int dist; // distance back to copy from - - internal byte lbits; // ltree bits decoded per branch - internal byte dbits; // dtree bits decoder per branch - internal int[] ltree; // literal/length/eob tree - internal int ltree_index; // literal/length/eob tree - internal int[] dtree; // distance tree - internal int dtree_index; // distance tree - - internal InflateCodes() - { - } - - internal void Init(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index) - { - mode = START; - lbits = (byte)bl; - dbits = (byte)bd; - ltree = tl; - ltree_index = tl_index; - dtree = td; - dtree_index = td_index; - tree = null; - } - - - internal int Process(InflateBlocks blocks, int r) - { - int j; // temporary storage - int tindex; // temporary pointer - int e; // extra bits or operation - int b = 0; // bit buffer - int k = 0; // bits in bit buffer - int p = 0; // input data pointer - int n; // bytes available there - int q; // output window write pointer - int m; // bytes to end of window or read pointer - int f; // pointer to copy strings from - - ZlibCodec z = blocks._codec; - - // copy input/output information to locals (UPDATE macro restores) - p = z.NextIn; - n = z.AvailableBytesIn; - b = blocks.bitb; - k = blocks.bitk; - q = blocks.writeAt; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; - - // process input and output based on current state - while (true) - { - switch (mode) - { - // waiting for "i:"=input, "o:"=output, "x:"=nothing - case START: // x: set up for LEN - if (m >= 258 && n >= 10) - { - blocks.bitb = b; blocks.bitk = k; - z.AvailableBytesIn = n; - z.TotalBytesIn += p - z.NextIn; - z.NextIn = p; - blocks.writeAt = q; - r = InflateFast(lbits, dbits, ltree, ltree_index, dtree, dtree_index, blocks, z); - - p = z.NextIn; - n = z.AvailableBytesIn; - b = blocks.bitb; - k = blocks.bitk; - q = blocks.writeAt; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; - - if (r != ZlibConstants.Z_OK) - { - mode = (r == ZlibConstants.Z_STREAM_END) ? WASH : BADCODE; - break; - } - } - need = lbits; - tree = ltree; - tree_index = ltree_index; - - mode = LEN; - goto case LEN; - - case LEN: // i: get length/literal/eob next - j = need; - - while (k < j) - { - if (n != 0) - r = ZlibConstants.Z_OK; - else - { - blocks.bitb = b; blocks.bitk = k; - z.AvailableBytesIn = n; - z.TotalBytesIn += p - z.NextIn; - z.NextIn = p; - blocks.writeAt = q; - return blocks.Flush(r); - } - n--; - b |= (z.InputBuffer[p++] & 0xff) << k; - k += 8; - } - - tindex = (tree_index + (b & InternalInflateConstants.InflateMask[j])) * 3; - - b >>= (tree[tindex + 1]); - k -= (tree[tindex + 1]); - - e = tree[tindex]; - - if (e == 0) - { - // literal - lit = tree[tindex + 2]; - mode = LIT; - break; - } - if ((e & 16) != 0) - { - // length - bitsToGet = e & 15; - len = tree[tindex + 2]; - mode = LENEXT; - break; - } - if ((e & 64) == 0) - { - // next table - need = e; - tree_index = tindex / 3 + tree[tindex + 2]; - break; - } - if ((e & 32) != 0) - { - // end of block - mode = WASH; - break; - } - mode = BADCODE; // invalid code - z.Message = "invalid literal/length code"; - r = ZlibConstants.Z_DATA_ERROR; - - blocks.bitb = b; blocks.bitk = k; - z.AvailableBytesIn = n; - z.TotalBytesIn += p - z.NextIn; - z.NextIn = p; - blocks.writeAt = q; - return blocks.Flush(r); - - - case LENEXT: // i: getting length extra (have base) - j = bitsToGet; - - while (k < j) - { - if (n != 0) - r = ZlibConstants.Z_OK; - else - { - blocks.bitb = b; blocks.bitk = k; - z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; - blocks.writeAt = q; - return blocks.Flush(r); - } - n--; b |= (z.InputBuffer[p++] & 0xff) << k; - k += 8; - } - - len += (b & InternalInflateConstants.InflateMask[j]); - - b >>= j; - k -= j; - - need = dbits; - tree = dtree; - tree_index = dtree_index; - mode = DIST; - goto case DIST; - - case DIST: // i: get distance next - j = need; - - while (k < j) - { - if (n != 0) - r = ZlibConstants.Z_OK; - else - { - blocks.bitb = b; blocks.bitk = k; - z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; - blocks.writeAt = q; - return blocks.Flush(r); - } - n--; b |= (z.InputBuffer[p++] & 0xff) << k; - k += 8; - } - - tindex = (tree_index + (b & InternalInflateConstants.InflateMask[j])) * 3; - - b >>= tree[tindex + 1]; - k -= tree[tindex + 1]; - - e = (tree[tindex]); - if ((e & 0x10) != 0) - { - // distance - bitsToGet = e & 15; - dist = tree[tindex + 2]; - mode = DISTEXT; - break; - } - if ((e & 64) == 0) - { - // next table - need = e; - tree_index = tindex / 3 + tree[tindex + 2]; - break; - } - mode = BADCODE; // invalid code - z.Message = "invalid distance code"; - r = ZlibConstants.Z_DATA_ERROR; - - blocks.bitb = b; blocks.bitk = k; - z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; - blocks.writeAt = q; - return blocks.Flush(r); - - - case DISTEXT: // i: getting distance extra - j = bitsToGet; - - while (k < j) - { - if (n != 0) - r = ZlibConstants.Z_OK; - else - { - blocks.bitb = b; blocks.bitk = k; - z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; - blocks.writeAt = q; - return blocks.Flush(r); - } - n--; b |= (z.InputBuffer[p++] & 0xff) << k; - k += 8; - } - - dist += (b & InternalInflateConstants.InflateMask[j]); - - b >>= j; - k -= j; - - mode = COPY; - goto case COPY; - - case COPY: // o: copying bytes in window, waiting for space - f = q - dist; - while (f < 0) - { - // modulo window size-"while" instead - f += blocks.end; // of "if" handles invalid distances - } - while (len != 0) - { - if (m == 0) - { - if (q == blocks.end && blocks.readAt != 0) - { - q = 0; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; - } - if (m == 0) - { - blocks.writeAt = q; r = blocks.Flush(r); - q = blocks.writeAt; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; - - if (q == blocks.end && blocks.readAt != 0) - { - q = 0; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; - } - - if (m == 0) - { - blocks.bitb = b; blocks.bitk = k; - z.AvailableBytesIn = n; - z.TotalBytesIn += p - z.NextIn; - z.NextIn = p; - blocks.writeAt = q; - return blocks.Flush(r); - } - } - } - - blocks.window[q++] = blocks.window[f++]; m--; - - if (f == blocks.end) - f = 0; - len--; - } - mode = START; - break; - - case LIT: // o: got literal, waiting for output space - if (m == 0) - { - if (q == blocks.end && blocks.readAt != 0) - { - q = 0; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; - } - if (m == 0) - { - blocks.writeAt = q; r = blocks.Flush(r); - q = blocks.writeAt; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; - - if (q == blocks.end && blocks.readAt != 0) - { - q = 0; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; - } - if (m == 0) - { - blocks.bitb = b; blocks.bitk = k; - z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; - blocks.writeAt = q; - return blocks.Flush(r); - } - } - } - r = ZlibConstants.Z_OK; - - blocks.window[q++] = (byte)lit; m--; - - mode = START; - break; - - case WASH: // o: got eob, possibly more output - if (k > 7) - { - // return unused byte, if any - k -= 8; - n++; - p--; // can always return one - } - - blocks.writeAt = q; r = blocks.Flush(r); - q = blocks.writeAt; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q; - - if (blocks.readAt != blocks.writeAt) - { - blocks.bitb = b; blocks.bitk = k; - z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; - blocks.writeAt = q; - return blocks.Flush(r); - } - mode = END; - goto case END; - - case END: - r = ZlibConstants.Z_STREAM_END; - blocks.bitb = b; blocks.bitk = k; - z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; - blocks.writeAt = q; - return blocks.Flush(r); - - case BADCODE: // x: got error - - r = ZlibConstants.Z_DATA_ERROR; - - blocks.bitb = b; blocks.bitk = k; - z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; - blocks.writeAt = q; - return blocks.Flush(r); - - default: - r = ZlibConstants.Z_STREAM_ERROR; - - blocks.bitb = b; blocks.bitk = k; - z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; - blocks.writeAt = q; - return blocks.Flush(r); - } - } - } - - - // Called with number of bytes left to write in window at least 258 - // (the maximum string length) and number of input bytes available - // at least ten. The ten bytes are six bytes for the longest length/ - // distance pair plus four bytes for overloading the bit buffer. - [MethodImpl(MethodImplOptions.AggressiveOptimization)] - internal int InflateFast(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index, InflateBlocks s, ZlibCodec z) - { - int t; // temporary pointer - int[] tp; // temporary pointer - int tp_index; // temporary pointer - int e; // extra bits or operation - int b; // bit buffer - int k; // bits in bit buffer - int p; // input data pointer - int n; // bytes available there - int q; // output window write pointer - int m; // bytes to end of window or read pointer - int ml; // mask for literal/length tree - int md; // mask for distance tree - int c; // bytes to copy - int d; // distance back to copy from - int r; // copy source pointer - - int tp_index_t_3; // (tp_index+t)*3 - - // load input, output, bit values - p = z.NextIn; n = z.AvailableBytesIn; b = s.bitb; k = s.bitk; - q = s.writeAt; m = q < s.readAt ? s.readAt - q - 1 : s.end - q; - - // initialize masks - ml = InternalInflateConstants.InflateMask[bl]; - md = InternalInflateConstants.InflateMask[bd]; - - // do until not enough input or output space for fast loop - do - { - // assume called with m >= 258 && n >= 10 - // get literal/length code - while (k < (20)) - { - // max bits for literal/length code - n--; - b |= (z.InputBuffer[p++] & 0xff) << k; k += 8; - } - - t = b & ml; - tp = tl; - tp_index = tl_index; - tp_index_t_3 = (tp_index + t) * 3; - if ((e = tp[tp_index_t_3]) == 0) - { - b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]); - - s.window[q++] = (byte)tp[tp_index_t_3 + 2]; - m--; - continue; - } - do - { - - b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]); - - if ((e & 16) != 0) - { - e &= 15; - c = tp[tp_index_t_3 + 2] + ((int)b & InternalInflateConstants.InflateMask[e]); - - b >>= e; k -= e; - - // decode distance base of block to copy - while (k < 15) - { - // max bits for distance code - n--; - b |= (z.InputBuffer[p++] & 0xff) << k; k += 8; - } - - t = b & md; - tp = td; - tp_index = td_index; - tp_index_t_3 = (tp_index + t) * 3; - e = tp[tp_index_t_3]; - - do - { - - b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]); - - if ((e & 16) != 0) - { - // get extra bits to add to distance base - e &= 15; - while (k < e) - { - // get extra bits (up to 13) - n--; - b |= (z.InputBuffer[p++] & 0xff) << k; k += 8; - } - - d = tp[tp_index_t_3 + 2] + (b & InternalInflateConstants.InflateMask[e]); - - b >>= e; k -= e; - - // do the copy - m -= c; - if (q >= d) - { - // offset before dest - // just copy - r = q - d; - if (q - r > 0 && 2 > (q - r)) - { - s.window[q++] = s.window[r++]; // minimum count is three, - s.window[q++] = s.window[r++]; // so unroll loop a little - c -= 2; - } - else - { - Array.Copy(s.window, r, s.window, q, 2); - q += 2; r += 2; c -= 2; - } - } - else - { - // else offset after destination - r = q - d; - do - { - r += s.end; // force pointer in window - } - while (r < 0); // covers invalid distances - e = s.end - r; - if (c > e) - { - // if source crosses, - c -= e; // wrapped copy - if (q - r > 0 && e > (q - r)) - { - do - { - s.window[q++] = s.window[r++]; - } - while (--e != 0); - } - else - { - Array.Copy(s.window, r, s.window, q, e); - q += e; r += e; e = 0; - } - r = 0; // copy rest from start of window - } - } - - // copy all or what's left - if (q - r > 0 && c > (q - r)) - { - do - { - s.window[q++] = s.window[r++]; - } - while (--c != 0); - } - else - { - Array.Copy(s.window, r, s.window, q, c); - q += c; r += c; c = 0; - } - break; - } - else if ((e & 64) == 0) - { - t += tp[tp_index_t_3 + 2]; - t += (b & InternalInflateConstants.InflateMask[e]); - tp_index_t_3 = (tp_index + t) * 3; - e = tp[tp_index_t_3]; - } - else - { - z.Message = "invalid distance code"; - - c = z.AvailableBytesIn - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= (c << 3); - - s.bitb = b; s.bitk = k; - z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; - s.writeAt = q; - - return ZlibConstants.Z_DATA_ERROR; - } - } - while (true); - break; - } - - if ((e & 64) == 0) - { - t += tp[tp_index_t_3 + 2]; - t += (b & InternalInflateConstants.InflateMask[e]); - tp_index_t_3 = (tp_index + t) * 3; - if ((e = tp[tp_index_t_3]) == 0) - { - b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]); - s.window[q++] = (byte)tp[tp_index_t_3 + 2]; - m--; - break; - } - } - else if ((e & 32) != 0) - { - c = z.AvailableBytesIn - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= (c << 3); - - s.bitb = b; s.bitk = k; - z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; - s.writeAt = q; - - return ZlibConstants.Z_STREAM_END; - } - else - { - z.Message = "invalid literal/length code"; - - c = z.AvailableBytesIn - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= (c << 3); - - s.bitb = b; s.bitk = k; - z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; - s.writeAt = q; - - return ZlibConstants.Z_DATA_ERROR; - } - } - while (true); - } - while (m >= 258 && n >= 10); - - // not enough input or output--restore pointers and return - c = z.AvailableBytesIn - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= (c << 3); - - s.bitb = b; s.bitk = k; - z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p; - s.writeAt = q; - - return ZlibConstants.Z_OK; - } - } - - - internal sealed class InflateManager - { - // preset dictionary flag in zlib header - private const int PRESET_DICT = 0x20; - - private const int Z_DEFLATED = 8; - - private enum InflateManagerMode - { - METHOD = 0, // waiting for method byte - FLAG = 1, // waiting for flag byte - DICT4 = 2, // four dictionary check bytes to go - DICT3 = 3, // three dictionary check bytes to go - DICT2 = 4, // two dictionary check bytes to go - DICT1 = 5, // one dictionary check byte to go - DICT0 = 6, // waiting for inflateSetDictionary - BLOCKS = 7, // decompressing blocks - CHECK4 = 8, // four check bytes to go - CHECK3 = 9, // three check bytes to go - CHECK2 = 10, // two check bytes to go - CHECK1 = 11, // one check byte to go - DONE = 12, // finished check, done - BAD = 13, // got an error--stay here - } - - private InflateManagerMode mode; // current inflate mode - internal ZlibCodec _codec; // pointer back to this zlib stream - - // mode dependent information - internal int method; // if FLAGS, method byte - - // if CHECK, check values to compare - internal uint computedCheck; // computed check value - internal uint expectedCheck; // stream check value - - // if BAD, inflateSync's marker bytes count - internal int marker; - - // mode independent information - //internal int nowrap; // flag for no wrapper - private bool _handleRfc1950HeaderBytes = true; - internal bool HandleRfc1950HeaderBytes - { - get { return _handleRfc1950HeaderBytes; } - set { _handleRfc1950HeaderBytes = value; } - } - internal int wbits; // log2(window size) (8..15, defaults to 15) - - internal InflateBlocks blocks; // current inflate_blocks state - - public InflateManager() { } - - public InflateManager(bool expectRfc1950HeaderBytes) - { - _handleRfc1950HeaderBytes = expectRfc1950HeaderBytes; - } - - internal int Reset() - { - _codec.TotalBytesIn = _codec.TotalBytesOut = 0; - _codec.Message = null; - mode = HandleRfc1950HeaderBytes ? InflateManagerMode.METHOD : InflateManagerMode.BLOCKS; - blocks.Reset(); - return ZlibConstants.Z_OK; - } - - internal int End() - { - if (blocks != null) - blocks.Free(); - blocks = null; - return ZlibConstants.Z_OK; - } - - internal int Initialize(ZlibCodec codec, int w) - { - _codec = codec; - _codec.Message = null; - blocks = null; - - // handle undocumented nowrap option (no zlib header or check) - //nowrap = 0; - //if (w < 0) - //{ - // w = - w; - // nowrap = 1; - //} - - // set window size - if (w < 8 || w > 15) - { - End(); - throw new ZlibException("Bad window size."); - - //return ZlibConstants.Z_STREAM_ERROR; - } - wbits = w; - - blocks = new InflateBlocks(codec, - HandleRfc1950HeaderBytes ? this : null, - 1 << w); - - // reset state - Reset(); - return ZlibConstants.Z_OK; - } - - - internal int Inflate(FlushType flush) - { - int b; - - if (_codec.InputBuffer == null) - throw new ZlibException("InputBuffer is null. "); - - // int f = (flush == FlushType.Finish) - // ? ZlibConstants.Z_BUF_ERROR - // : ZlibConstants.Z_OK; - - // workitem 8870 - int f = ZlibConstants.Z_OK; - int r = ZlibConstants.Z_BUF_ERROR; - - while (true) - { - switch (mode) - { - case InflateManagerMode.METHOD: - if (_codec.AvailableBytesIn == 0) return r; - r = f; - _codec.AvailableBytesIn--; - _codec.TotalBytesIn++; - if (((method = _codec.InputBuffer[_codec.NextIn++]) & 0xf) != Z_DEFLATED) - { - mode = InflateManagerMode.BAD; - _codec.Message = String.Format("unknown compression method (0x{0:X2})", method); - marker = 5; // can't try inflateSync - break; - } - if ((method >> 4) + 8 > wbits) - { - mode = InflateManagerMode.BAD; - _codec.Message = String.Format("invalid window size ({0})", (method >> 4) + 8); - marker = 5; // can't try inflateSync - break; - } - mode = InflateManagerMode.FLAG; - break; - - - case InflateManagerMode.FLAG: - if (_codec.AvailableBytesIn == 0) return r; - r = f; - _codec.AvailableBytesIn--; - _codec.TotalBytesIn++; - b = (_codec.InputBuffer[_codec.NextIn++]) & 0xff; - - if ((((method << 8) + b) % 31) != 0) - { - mode = InflateManagerMode.BAD; - _codec.Message = "incorrect header check"; - marker = 5; // can't try inflateSync - break; - } - - mode = ((b & PRESET_DICT) == 0) - ? InflateManagerMode.BLOCKS - : InflateManagerMode.DICT4; - break; - - case InflateManagerMode.DICT4: - if (_codec.AvailableBytesIn == 0) return r; - r = f; - _codec.AvailableBytesIn--; - _codec.TotalBytesIn++; - expectedCheck = (uint)((_codec.InputBuffer[_codec.NextIn++] << 24) & 0xff000000); - mode = InflateManagerMode.DICT3; - break; - - case InflateManagerMode.DICT3: - if (_codec.AvailableBytesIn == 0) return r; - r = f; - _codec.AvailableBytesIn--; - _codec.TotalBytesIn++; - expectedCheck += (uint)((_codec.InputBuffer[_codec.NextIn++] << 16) & 0x00ff0000); - mode = InflateManagerMode.DICT2; - break; - - case InflateManagerMode.DICT2: - - if (_codec.AvailableBytesIn == 0) return r; - r = f; - _codec.AvailableBytesIn--; - _codec.TotalBytesIn++; - expectedCheck += (uint)((_codec.InputBuffer[_codec.NextIn++] << 8) & 0x0000ff00); - mode = InflateManagerMode.DICT1; - break; - - - case InflateManagerMode.DICT1: - if (_codec.AvailableBytesIn == 0) return r; - r = f; - _codec.AvailableBytesIn--; _codec.TotalBytesIn++; - expectedCheck += (uint)(_codec.InputBuffer[_codec.NextIn++] & 0x000000ff); - _codec._Adler32 = expectedCheck; - mode = InflateManagerMode.DICT0; - return ZlibConstants.Z_NEED_DICT; - - - case InflateManagerMode.DICT0: - mode = InflateManagerMode.BAD; - _codec.Message = "need dictionary"; - marker = 0; // can try inflateSync - return ZlibConstants.Z_STREAM_ERROR; - - - case InflateManagerMode.BLOCKS: - r = blocks.Process(r); - if (r == ZlibConstants.Z_DATA_ERROR) - { - mode = InflateManagerMode.BAD; - marker = 0; // can try inflateSync - break; - } - - if (r == ZlibConstants.Z_OK) r = f; - - if (r != ZlibConstants.Z_STREAM_END) - return r; - - r = f; - computedCheck = blocks.Reset(); - if (!HandleRfc1950HeaderBytes) - { - mode = InflateManagerMode.DONE; - return ZlibConstants.Z_STREAM_END; - } - mode = InflateManagerMode.CHECK4; - break; - - case InflateManagerMode.CHECK4: - if (_codec.AvailableBytesIn == 0) return r; - r = f; - _codec.AvailableBytesIn--; - _codec.TotalBytesIn++; - expectedCheck = (uint)((_codec.InputBuffer[_codec.NextIn++] << 24) & 0xff000000); - mode = InflateManagerMode.CHECK3; - break; - - case InflateManagerMode.CHECK3: - if (_codec.AvailableBytesIn == 0) return r; - r = f; - _codec.AvailableBytesIn--; _codec.TotalBytesIn++; - expectedCheck += (uint)((_codec.InputBuffer[_codec.NextIn++] << 16) & 0x00ff0000); - mode = InflateManagerMode.CHECK2; - break; - - case InflateManagerMode.CHECK2: - if (_codec.AvailableBytesIn == 0) return r; - r = f; - _codec.AvailableBytesIn--; - _codec.TotalBytesIn++; - expectedCheck += (uint)((_codec.InputBuffer[_codec.NextIn++] << 8) & 0x0000ff00); - mode = InflateManagerMode.CHECK1; - break; - - case InflateManagerMode.CHECK1: - if (_codec.AvailableBytesIn == 0) return r; - r = f; - _codec.AvailableBytesIn--; _codec.TotalBytesIn++; - expectedCheck += (uint)(_codec.InputBuffer[_codec.NextIn++] & 0x000000ff); - if (computedCheck != expectedCheck) - { - mode = InflateManagerMode.BAD; - _codec.Message = "incorrect data check"; - marker = 5; // can't try inflateSync - break; - } - mode = InflateManagerMode.DONE; - return ZlibConstants.Z_STREAM_END; - - case InflateManagerMode.DONE: - return ZlibConstants.Z_STREAM_END; - - case InflateManagerMode.BAD: - throw new ZlibException(String.Format("Bad state ({0})", _codec.Message)); - - default: - throw new ZlibException("Stream error."); - - } - } - } - - - - internal int SetDictionary(byte[] dictionary) - { - int index = 0; - int length = dictionary.Length; - if (mode != InflateManagerMode.DICT0) - throw new ZlibException("Stream error."); - - if (Adler.Adler32(1, dictionary, 0, dictionary.Length) != _codec._Adler32) - { - return ZlibConstants.Z_DATA_ERROR; - } - - _codec._Adler32 = Adler.Adler32(0, null, 0, 0); - - if (length >= (1 << wbits)) - { - length = (1 << wbits) - 1; - index = dictionary.Length - length; - } - blocks.SetDictionary(dictionary, index, length); - mode = InflateManagerMode.BLOCKS; - return ZlibConstants.Z_OK; - } - - - private static readonly byte[] mark = new byte[] { 0, 0, 0xff, 0xff }; - - internal int Sync() - { - int n; // number of bytes to look at - int p; // pointer to bytes - int m; // number of marker bytes found in a row - long r, w; // temporaries to save total_in and total_out - - // set up - if (mode != InflateManagerMode.BAD) - { - mode = InflateManagerMode.BAD; - marker = 0; - } - if ((n = _codec.AvailableBytesIn) == 0) - return ZlibConstants.Z_BUF_ERROR; - p = _codec.NextIn; - m = marker; - - // search - while (n != 0 && m < 4) - { - if (_codec.InputBuffer[p] == mark[m]) - { - m++; - } - else if (_codec.InputBuffer[p] != 0) - { - m = 0; - } - else - { - m = 4 - m; - } - p++; n--; - } - - // restore - _codec.TotalBytesIn += p - _codec.NextIn; - _codec.NextIn = p; - _codec.AvailableBytesIn = n; - marker = m; - - // return no joy or set up to restart on a new block - if (m != 4) - { - return ZlibConstants.Z_DATA_ERROR; - } - r = _codec.TotalBytesIn; - w = _codec.TotalBytesOut; - Reset(); - _codec.TotalBytesIn = r; - _codec.TotalBytesOut = w; - mode = InflateManagerMode.BLOCKS; - return ZlibConstants.Z_OK; - } - - - // Returns true if inflate is currently at the end of a block generated - // by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP - // implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH - // but removes the length bytes of the resulting empty stored block. When - // decompressing, PPP checks that at the end of input packet, inflate is - // waiting for these length bytes. - internal int SyncPoint(ZlibCodec z) - { - return blocks.SyncPoint(); - } - } -} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/Compression/ParallelDeflateOutputStream.cs b/MinecraftClient/Protocol/Handlers/Compression/ParallelDeflateOutputStream.cs deleted file mode 100644 index f7514159..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/ParallelDeflateOutputStream.cs +++ /dev/null @@ -1,1386 +0,0 @@ -//#define Trace - -// ParallelDeflateOutputStream.cs -// ------------------------------------------------------------------ -// -// A DeflateStream that does compression only, it uses a -// divide-and-conquer approach with multiple threads to exploit multiple -// CPUs for the DEFLATE computation. -// -// last saved: <2011-July-31 14:49:40> -// -// ------------------------------------------------------------------ -// -// Copyright (c) 2009-2011 by 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 -// -// ------------------------------------------------------------------ - -using System; -using System.Collections.Generic; -using System.Threading; -using Ionic.Zlib; -using System.IO; - - -namespace Ionic.Zlib -{ - internal class WorkItem - { - public byte[] buffer; - public byte[] compressed; - public int crc; - public int index; - public int ordinal; - public int inputBytesAvailable; - public int compressedBytesAvailable; - public ZlibCodec compressor; - - public WorkItem(int size, - Ionic.Zlib.CompressionLevel compressLevel, - CompressionStrategy strategy, - int ix) - { - this.buffer= new byte[size]; - // alloc 5 bytes overhead for every block (margin of safety= 2) - int n = size + ((size / 32768)+1) * 5 * 2; - this.compressed = new byte[n]; - this.compressor = new ZlibCodec(); - this.compressor.InitializeDeflate(compressLevel, false); - this.compressor.OutputBuffer = this.compressed; - this.compressor.InputBuffer = this.buffer; - this.index = ix; - } - } - - /// - /// A class for compressing streams using the - /// Deflate algorithm with multiple threads. - /// - /// - /// - /// - /// This class performs DEFLATE compression through writing. For - /// more information on the Deflate algorithm, see IETF RFC 1951, - /// "DEFLATE Compressed Data Format Specification version 1.3." - /// - /// - /// - /// This class is similar to , except - /// that this class is for compression only, and this implementation uses an - /// approach that employs multiple worker threads to perform the DEFLATE. On - /// a multi-cpu or multi-core computer, the performance of this class can be - /// significantly higher than the single-threaded DeflateStream, particularly - /// for larger streams. How large? Anything over 10mb is a good candidate - /// for parallel compression. - /// - /// - /// - /// The tradeoff is that this class uses more memory and more CPU than the - /// vanilla DeflateStream, and also is less efficient as a compressor. For - /// large files the size of the compressed data stream can be less than 1% - /// larger than the size of a compressed data stream from the vanialla - /// DeflateStream. For smaller files the difference can be larger. The - /// difference will also be larger if you set the BufferSize to be lower than - /// the default value. Your mileage may vary. Finally, for small files, the - /// ParallelDeflateOutputStream can be much slower than the vanilla - /// DeflateStream, because of the overhead associated to using the thread - /// pool. - /// - /// - /// - /// - public class ParallelDeflateOutputStream : System.IO.Stream - { - - private static readonly int IO_BUFFER_SIZE_DEFAULT = 64 * 1024; // 128k - private static readonly int BufferPairsPerCore = 4; - - private System.Collections.Generic.List _pool; - private bool _leaveOpen; - private bool emitting; - private System.IO.Stream _outStream; - private int _maxBufferPairs; - private int _bufferSize = IO_BUFFER_SIZE_DEFAULT; - private AutoResetEvent _newlyCompressedBlob; - //private ManualResetEvent _writingDone; - //private ManualResetEvent _sessionReset; - private object _outputLock = new object(); - private bool _isClosed; - private bool _firstWriteDone; - private int _currentlyFilling; - private int _lastFilled; - private int _lastWritten; - private int _latestCompressed; - private int _Crc32; - private Ionic.Crc.CRC32 _runningCrc; - private object _latestLock = new object(); - private System.Collections.Generic.Queue _toWrite; - private System.Collections.Generic.Queue _toFill; - private Int64 _totalBytesProcessed; - private Ionic.Zlib.CompressionLevel _compressLevel; - private volatile Exception _pendingException; - private bool _handlingException; - private object _eLock = new Object(); // protects _pendingException - - // This bitfield is used only when Trace is defined. - //private TraceBits _DesiredTrace = TraceBits.Write | TraceBits.WriteBegin | - //TraceBits.WriteDone | TraceBits.Lifecycle | TraceBits.Fill | TraceBits.Flush | - //TraceBits.Session; - - //private TraceBits _DesiredTrace = TraceBits.WriteBegin | TraceBits.WriteDone | TraceBits.Synch | TraceBits.Lifecycle | TraceBits.Session ; - - private TraceBits _DesiredTrace = - TraceBits.Session | - TraceBits.Compress | - TraceBits.WriteTake | - TraceBits.WriteEnter | - TraceBits.EmitEnter | - TraceBits.EmitDone | - TraceBits.EmitLock | - TraceBits.EmitSkip | - TraceBits.EmitBegin; - - /// - /// Create a ParallelDeflateOutputStream. - /// - /// - /// - /// - /// This stream compresses data written into it via the DEFLATE - /// algorithm (see RFC 1951), and writes out the compressed byte stream. - /// - /// - /// - /// The instance will use the default compression level, the default - /// buffer sizes and the default number of threads and buffers per - /// thread. - /// - /// - /// - /// This class is similar to , - /// except that this implementation uses an approach that employs - /// multiple worker threads to perform the DEFLATE. On a multi-cpu or - /// multi-core computer, the performance of this class can be - /// significantly higher than the single-threaded DeflateStream, - /// particularly for larger streams. How large? Anything over 10mb is - /// a good candidate for parallel compression. - /// - /// - /// - /// - /// - /// - /// This example shows how to use a ParallelDeflateOutputStream to compress - /// data. It reads a file, compresses it, and writes the compressed data to - /// a second, output file. - /// - /// - /// byte[] buffer = new byte[WORKING_BUFFER_SIZE]; - /// int n= -1; - /// String outputFile = fileToCompress + ".compressed"; - /// using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) - /// { - /// using (var raw = System.IO.File.Create(outputFile)) - /// { - /// using (Stream compressor = new ParallelDeflateOutputStream(raw)) - /// { - /// while ((n= input.Read(buffer, 0, buffer.Length)) != 0) - /// { - /// compressor.Write(buffer, 0, n); - /// } - /// } - /// } - /// } - /// - /// - /// Dim buffer As Byte() = New Byte(4096) {} - /// Dim n As Integer = -1 - /// Dim outputFile As String = (fileToCompress & ".compressed") - /// Using input As Stream = File.OpenRead(fileToCompress) - /// Using raw As FileStream = File.Create(outputFile) - /// Using compressor As Stream = New ParallelDeflateOutputStream(raw) - /// Do While (n <> 0) - /// If (n > 0) Then - /// compressor.Write(buffer, 0, n) - /// End If - /// n = input.Read(buffer, 0, buffer.Length) - /// Loop - /// End Using - /// End Using - /// End Using - /// - /// - /// The stream to which compressed data will be written. - public ParallelDeflateOutputStream(System.IO.Stream stream) - : this(stream, CompressionLevel.Default, CompressionStrategy.Default, false) - { - } - - /// - /// Create a ParallelDeflateOutputStream using the specified CompressionLevel. - /// - /// - /// See the - /// constructor for example code. - /// - /// The stream to which compressed data will be written. - /// A tuning knob to trade speed for effectiveness. - public ParallelDeflateOutputStream(System.IO.Stream stream, CompressionLevel level) - : this(stream, level, CompressionStrategy.Default, false) - { - } - - /// - /// Create a ParallelDeflateOutputStream and specify whether to leave the captive stream open - /// when the ParallelDeflateOutputStream is closed. - /// - /// - /// See the - /// constructor for example code. - /// - /// The stream to which compressed data will be written. - /// - /// true if the application would like the stream to remain open after inflation/deflation. - /// - public ParallelDeflateOutputStream(System.IO.Stream stream, bool leaveOpen) - : this(stream, CompressionLevel.Default, CompressionStrategy.Default, leaveOpen) - { - } - - /// - /// Create a ParallelDeflateOutputStream and specify whether to leave the captive stream open - /// when the ParallelDeflateOutputStream is closed. - /// - /// - /// See the - /// constructor for example code. - /// - /// The stream to which compressed data will be written. - /// A tuning knob to trade speed for effectiveness. - /// - /// true if the application would like the stream to remain open after inflation/deflation. - /// - public ParallelDeflateOutputStream(System.IO.Stream stream, CompressionLevel level, bool leaveOpen) - : this(stream, CompressionLevel.Default, CompressionStrategy.Default, leaveOpen) - { - } - - /// - /// Create a ParallelDeflateOutputStream using the specified - /// CompressionLevel and CompressionStrategy, and specifying whether to - /// leave the captive stream open when the ParallelDeflateOutputStream is - /// closed. - /// - /// - /// See the - /// constructor for example code. - /// - /// The stream to which compressed data will be written. - /// A tuning knob to trade speed for effectiveness. - /// - /// By tweaking this parameter, you may be able to optimize the compression for - /// data with particular characteristics. - /// - /// - /// true if the application would like the stream to remain open after inflation/deflation. - /// - public ParallelDeflateOutputStream(System.IO.Stream stream, - CompressionLevel level, - CompressionStrategy strategy, - bool leaveOpen) - { - TraceOutput(TraceBits.Lifecycle | TraceBits.Session, "-------------------------------------------------------"); - TraceOutput(TraceBits.Lifecycle | TraceBits.Session, "Create {0:X8}", this.GetHashCode()); - _outStream = stream; - _compressLevel= level; - Strategy = strategy; - _leaveOpen = leaveOpen; - this.MaxBufferPairs = 16; // default - } - - - /// - /// The ZLIB strategy to be used during compression. - /// - /// - public CompressionStrategy Strategy - { - get; - private set; - } - - /// - /// The maximum number of buffer pairs to use. - /// - /// - /// - /// - /// This property sets an upper limit on the number of memory buffer - /// pairs to create. The implementation of this stream allocates - /// multiple buffers to facilitate parallel compression. As each buffer - /// fills up, this stream uses - /// ThreadPool.QueueUserWorkItem() - /// to compress those buffers in a background threadpool thread. After a - /// buffer is compressed, it is re-ordered and written to the output - /// stream. - /// - /// - /// - /// A higher number of buffer pairs enables a higher degree of - /// parallelism, which tends to increase the speed of compression on - /// multi-cpu computers. On the other hand, a higher number of buffer - /// pairs also implies a larger memory consumption, more active worker - /// threads, and a higher cpu utilization for any compression. This - /// property enables the application to limit its memory consumption and - /// CPU utilization behavior depending on requirements. - /// - /// - /// - /// For each compression "task" that occurs in parallel, there are 2 - /// buffers allocated: one for input and one for output. This property - /// sets a limit for the number of pairs. The total amount of storage - /// space allocated for buffering will then be (N*S*2), where N is the - /// number of buffer pairs, S is the size of each buffer (). By default, DotNetZip allocates 4 buffer - /// pairs per CPU core, so if your machine has 4 cores, and you retain - /// the default buffer size of 128k, then the - /// ParallelDeflateOutputStream will use 4 * 4 * 2 * 128kb of buffer - /// memory in total, or 4mb, in blocks of 128kb. If you then set this - /// property to 8, then the number will be 8 * 2 * 128kb of buffer - /// memory, or 2mb. - /// - /// - /// - /// CPU utilization will also go up with additional buffers, because a - /// larger number of buffer pairs allows a larger number of background - /// threads to compress in parallel. If you find that parallel - /// compression is consuming too much memory or CPU, you can adjust this - /// value downward. - /// - /// - /// - /// The default value is 16. Different values may deliver better or - /// worse results, depending on your priorities and the dynamic - /// performance characteristics of your storage and compute resources. - /// - /// - /// - /// This property is not the number of buffer pairs to use; it is an - /// upper limit. An illustration: Suppose you have an application that - /// uses the default value of this property (which is 16), and it runs - /// on a machine with 2 CPU cores. In that case, DotNetZip will allocate - /// 4 buffer pairs per CPU core, for a total of 8 pairs. The upper - /// limit specified by this property has no effect. - /// - /// - /// - /// The application can set this value at any time, but it is effective - /// only before the first call to Write(), which is when the buffers are - /// allocated. - /// - /// - public int MaxBufferPairs - { - get - { - return _maxBufferPairs; - } - set - { - if (value < 4) - throw new ArgumentException("MaxBufferPairs", - "Value must be 4 or greater."); - _maxBufferPairs = value; - } - } - - /// - /// The size of the buffers used by the compressor threads. - /// - /// - /// - /// - /// The default buffer size is 128k. The application can set this value - /// at any time, but it is effective only before the first Write(). - /// - /// - /// - /// Larger buffer sizes implies larger memory consumption but allows - /// more efficient compression. Using smaller buffer sizes consumes less - /// memory but may result in less effective compression. For example, - /// using the default buffer size of 128k, the compression delivered is - /// within 1% of the compression delivered by the single-threaded . On the other hand, using a - /// BufferSize of 8k can result in a compressed data stream that is 5% - /// larger than that delivered by the single-threaded - /// DeflateStream. Excessively small buffer sizes can also cause - /// the speed of the ParallelDeflateOutputStream to drop, because of - /// larger thread scheduling overhead dealing with many many small - /// buffers. - /// - /// - /// - /// The total amount of storage space allocated for buffering will be - /// (N*S*2), where N is the number of buffer pairs, and S is the size of - /// each buffer (this property). There are 2 buffers used by the - /// compressor, one for input and one for output. By default, DotNetZip - /// allocates 4 buffer pairs per CPU core, so if your machine has 4 - /// cores, then the number of buffer pairs used will be 16. If you - /// accept the default value of this property, 128k, then the - /// ParallelDeflateOutputStream will use 16 * 2 * 128kb of buffer memory - /// in total, or 4mb, in blocks of 128kb. If you set this property to - /// 64kb, then the number will be 16 * 2 * 64kb of buffer memory, or - /// 2mb. - /// - /// - /// - public int BufferSize - { - get { return _bufferSize;} - set - { - if (value < 1024) - throw new ArgumentOutOfRangeException("BufferSize", - "BufferSize must be greater than 1024 bytes"); - _bufferSize = value; - } - } - - /// - /// The CRC32 for the data that was written out, prior to compression. - /// - /// - /// This value is meaningful only after a call to Close(). - /// - public int Crc32 { get { return _Crc32; } } - - - /// - /// The total number of uncompressed bytes processed by the ParallelDeflateOutputStream. - /// - /// - /// This value is meaningful only after a call to Close(). - /// - public Int64 BytesProcessed { get { return _totalBytesProcessed; } } - - - private void _InitializePoolOfWorkItems() - { - _toWrite = new Queue(); - _toFill = new Queue(); - _pool = new System.Collections.Generic.List(); - int nTasks = BufferPairsPerCore * Environment.ProcessorCount; - nTasks = Math.Min(nTasks, _maxBufferPairs); - for(int i=0; i < nTasks; i++) - { - _pool.Add(new WorkItem(_bufferSize, _compressLevel, Strategy, i)); - _toFill.Enqueue(i); - } - - _newlyCompressedBlob = new AutoResetEvent(false); - _runningCrc = new Ionic.Crc.CRC32(); - _currentlyFilling = -1; - _lastFilled = -1; - _lastWritten = -1; - _latestCompressed = -1; - } - - - - - /// - /// Write data to the stream. - /// - /// - /// - /// - /// - /// To use the ParallelDeflateOutputStream to compress data, create a - /// ParallelDeflateOutputStream with CompressionMode.Compress, passing a - /// writable output stream. Then call Write() on that - /// ParallelDeflateOutputStream, providing uncompressed data as input. The - /// data sent to the output stream will be the compressed form of the data - /// written. - /// - /// - /// - /// To decompress data, use the class. - /// - /// - /// - /// The buffer holding data to write to the stream. - /// the offset within that data array to find the first byte to write. - /// the number of bytes to write. - public override void Write(byte[] buffer, int offset, int count) - { - bool mustWait = false; - - // This method does this: - // 0. handles any pending exceptions - // 1. write any buffers that are ready to be written, - // 2. fills a work buffer; when full, flip state to 'Filled', - // 3. if more data to be written, goto step 1 - - if (_isClosed) - throw new InvalidOperationException(); - - // dispense any exceptions that occurred on the BG threads - if (_pendingException != null) - { - _handlingException = true; - var pe = _pendingException; - _pendingException = null; - throw pe; - } - - if (count == 0) return; - - if (!_firstWriteDone) - { - // Want to do this on first Write, first session, and not in the - // constructor. We want to allow MaxBufferPairs to - // change after construction, but before first Write. - _InitializePoolOfWorkItems(); - _firstWriteDone = true; - } - - - do - { - // may need to make buffers available - EmitPendingBuffers(false, mustWait); - - mustWait = false; - // use current buffer, or get a new buffer to fill - int ix = -1; - if (_currentlyFilling >= 0) - { - ix = _currentlyFilling; - TraceOutput(TraceBits.WriteTake, - "Write notake wi({0}) lf({1})", - ix, - _lastFilled); - } - else - { - TraceOutput(TraceBits.WriteTake, "Write take?"); - if (_toFill.Count == 0) - { - // no available buffers, so... need to emit - // compressed buffers. - mustWait = true; - continue; - } - - ix = _toFill.Dequeue(); - TraceOutput(TraceBits.WriteTake, - "Write take wi({0}) lf({1})", - ix, - _lastFilled); - ++_lastFilled; // TODO: consider rollover? - } - - WorkItem workitem = _pool[ix]; - - int limit = ((workitem.buffer.Length - workitem.inputBytesAvailable) > count) - ? count - : (workitem.buffer.Length - workitem.inputBytesAvailable); - - workitem.ordinal = _lastFilled; - - TraceOutput(TraceBits.Write, - "Write lock wi({0}) ord({1}) iba({2})", - workitem.index, - workitem.ordinal, - workitem.inputBytesAvailable - ); - - // copy from the provided buffer to our workitem, starting at - // the tail end of whatever data we might have in there currently. - Buffer.BlockCopy(buffer, - offset, - workitem.buffer, - workitem.inputBytesAvailable, - limit); - - count -= limit; - offset += limit; - workitem.inputBytesAvailable += limit; - if (workitem.inputBytesAvailable == workitem.buffer.Length) - { - // No need for interlocked.increment: the Write() - // method is documented as not multi-thread safe, so - // we can assume Write() calls come in from only one - // thread. - TraceOutput(TraceBits.Write, - "Write QUWI wi({0}) ord({1}) iba({2}) nf({3})", - workitem.index, - workitem.ordinal, - workitem.inputBytesAvailable ); - - if (!ThreadPool.QueueUserWorkItem( _DeflateOne, workitem )) - throw new Exception("Cannot enqueue workitem"); - - _currentlyFilling = -1; // will get a new buffer next time - } - else - _currentlyFilling = ix; - - if (count > 0) - TraceOutput(TraceBits.WriteEnter, "Write more"); - } - while (count > 0); // until no more to write - - TraceOutput(TraceBits.WriteEnter, "Write exit"); - return; - } - - - - private void _FlushFinish() - { - // After writing a series of compressed buffers, each one closed - // with Flush.Sync, we now write the final one as Flush.Finish, - // and then stop. - byte[] buffer = new byte[128]; - var compressor = new ZlibCodec(); - int rc = compressor.InitializeDeflate(_compressLevel, false); - compressor.InputBuffer = null; - compressor.NextIn = 0; - compressor.AvailableBytesIn = 0; - compressor.OutputBuffer = buffer; - compressor.NextOut = 0; - compressor.AvailableBytesOut = buffer.Length; - rc = compressor.Deflate(FlushType.Finish); - - if (rc != ZlibConstants.Z_STREAM_END && rc != ZlibConstants.Z_OK) - throw new Exception("deflating: " + compressor.Message); - - if (buffer.Length - compressor.AvailableBytesOut > 0) - { - TraceOutput(TraceBits.EmitBegin, - "Emit begin flush bytes({0})", - buffer.Length - compressor.AvailableBytesOut); - - _outStream.Write(buffer, 0, buffer.Length - compressor.AvailableBytesOut); - - TraceOutput(TraceBits.EmitDone, - "Emit done flush"); - } - - compressor.EndDeflate(); - - _Crc32 = _runningCrc.Crc32Result; - } - - - private void _Flush(bool lastInput) - { - if (_isClosed) - throw new InvalidOperationException(); - - if (emitting) return; - - // compress any partial buffer - if (_currentlyFilling >= 0) - { - WorkItem workitem = _pool[_currentlyFilling]; - _DeflateOne(workitem); - _currentlyFilling = -1; // get a new buffer next Write() - } - - if (lastInput) - { - EmitPendingBuffers(true, false); - _FlushFinish(); - } - else - { - EmitPendingBuffers(false, false); - } - } - - - - /// - /// Flush the stream. - /// - public override void Flush() - { - if (_pendingException != null) - { - _handlingException = true; - var pe = _pendingException; - _pendingException = null; - throw pe; - } - if (_handlingException) - return; - - _Flush(false); - } - - - /// - /// Close the stream. - /// - /// - /// You must call Close on the stream to guarantee that all of the data written in has - /// been compressed, and the compressed data has been written out. - /// - public override void Close() - { - TraceOutput(TraceBits.Session, "Close {0:X8}", this.GetHashCode()); - - if (_pendingException != null) - { - _handlingException = true; - var pe = _pendingException; - _pendingException = null; - throw pe; - } - - if (_handlingException) - return; - - if (_isClosed) return; - - _Flush(true); - - if (!_leaveOpen) - _outStream.Close(); - - _isClosed= true; - } - - - - // workitem 10030 - implement a new Dispose method - - /// Dispose the object - /// - /// - /// Because ParallelDeflateOutputStream is IDisposable, the - /// application must call this method when finished using the instance. - /// - /// - /// This method is generally called implicitly upon exit from - /// a using scope in C# (Using in VB). - /// - /// - new public void Dispose() - { - TraceOutput(TraceBits.Lifecycle, "Dispose {0:X8}", this.GetHashCode()); - Close(); - _pool = null; - Dispose(true); - } - - - - /// The Dispose method - /// - /// indicates whether the Dispose method was invoked by user code. - /// - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - } - - - /// - /// Resets the stream for use with another stream. - /// - /// - /// Because the ParallelDeflateOutputStream is expensive to create, it - /// has been designed so that it can be recycled and re-used. You have - /// to call Close() on the stream first, then you can call Reset() on - /// it, to use it again on another stream. - /// - /// - /// - /// The new output stream for this era. - /// - /// - /// - /// - /// ParallelDeflateOutputStream deflater = null; - /// foreach (var inputFile in listOfFiles) - /// { - /// string outputFile = inputFile + ".compressed"; - /// using (System.IO.Stream input = System.IO.File.OpenRead(inputFile)) - /// { - /// using (var outStream = System.IO.File.Create(outputFile)) - /// { - /// if (deflater == null) - /// deflater = new ParallelDeflateOutputStream(outStream, - /// CompressionLevel.Best, - /// CompressionStrategy.Default, - /// true); - /// deflater.Reset(outStream); - /// - /// while ((n= input.Read(buffer, 0, buffer.Length)) != 0) - /// { - /// deflater.Write(buffer, 0, n); - /// } - /// } - /// } - /// } - /// - /// - public void Reset(Stream stream) - { - TraceOutput(TraceBits.Session, "-------------------------------------------------------"); - TraceOutput(TraceBits.Session, "Reset {0:X8} firstDone({1})", this.GetHashCode(), _firstWriteDone); - - if (!_firstWriteDone) return; - - // reset all status - _toWrite.Clear(); - _toFill.Clear(); - foreach (var workitem in _pool) - { - _toFill.Enqueue(workitem.index); - workitem.ordinal = -1; - } - - _firstWriteDone = false; - _totalBytesProcessed = 0L; - _runningCrc = new Ionic.Crc.CRC32(); - _isClosed= false; - _currentlyFilling = -1; - _lastFilled = -1; - _lastWritten = -1; - _latestCompressed = -1; - _outStream = stream; - } - - - - - private void EmitPendingBuffers(bool doAll, bool mustWait) - { - // When combining parallel deflation with a ZipSegmentedStream, it's - // possible for the ZSS to throw from within this method. In that - // case, Close/Dispose will be called on this stream, if this stream - // is employed within a using or try/finally pair as required. But - // this stream is unaware of the pending exception, so the Close() - // method invokes this method AGAIN. This can lead to a deadlock. - // Therefore, failfast if re-entering. - - if (emitting) return; - emitting = true; - if (doAll || mustWait) - _newlyCompressedBlob.WaitOne(); - - do - { - int firstSkip = -1; - int millisecondsToWait = doAll ? 200 : (mustWait ? -1 : 0); - int nextToWrite = -1; - - do - { - if (Monitor.TryEnter(_toWrite, millisecondsToWait)) - { - nextToWrite = -1; - try - { - if (_toWrite.Count > 0) - nextToWrite = _toWrite.Dequeue(); - } - finally - { - Monitor.Exit(_toWrite); - } - - if (nextToWrite >= 0) - { - WorkItem workitem = _pool[nextToWrite]; - if (workitem.ordinal != _lastWritten + 1) - { - // out of order. requeue and try again. - TraceOutput(TraceBits.EmitSkip, - "Emit skip wi({0}) ord({1}) lw({2}) fs({3})", - workitem.index, - workitem.ordinal, - _lastWritten, - firstSkip); - - lock(_toWrite) - { - _toWrite.Enqueue(nextToWrite); - } - - if (firstSkip == nextToWrite) - { - // We went around the list once. - // None of the items in the list is the one we want. - // Now wait for a compressor to signal again. - _newlyCompressedBlob.WaitOne(); - firstSkip = -1; - } - else if (firstSkip == -1) - firstSkip = nextToWrite; - - continue; - } - - firstSkip = -1; - - TraceOutput(TraceBits.EmitBegin, - "Emit begin wi({0}) ord({1}) cba({2})", - workitem.index, - workitem.ordinal, - workitem.compressedBytesAvailable); - - _outStream.Write(workitem.compressed, 0, workitem.compressedBytesAvailable); - _runningCrc.Combine(workitem.crc, workitem.inputBytesAvailable); - _totalBytesProcessed += workitem.inputBytesAvailable; - workitem.inputBytesAvailable = 0; - - TraceOutput(TraceBits.EmitDone, - "Emit done wi({0}) ord({1}) cba({2}) mtw({3})", - workitem.index, - workitem.ordinal, - workitem.compressedBytesAvailable, - millisecondsToWait); - - _lastWritten = workitem.ordinal; - _toFill.Enqueue(workitem.index); - - // don't wait next time through - if (millisecondsToWait == -1) millisecondsToWait = 0; - } - } - else - nextToWrite = -1; - - } while (nextToWrite >= 0); - - } while (doAll && (_lastWritten != _latestCompressed)); - - emitting = false; - } - - - -#if OLD - private void _PerpetualWriterMethod(object state) - { - TraceOutput(TraceBits.WriterThread, "_PerpetualWriterMethod START"); - - try - { - do - { - // wait for the next session - TraceOutput(TraceBits.Synch | TraceBits.WriterThread, "Synch _sessionReset.WaitOne(begin) PWM"); - _sessionReset.WaitOne(); - TraceOutput(TraceBits.Synch | TraceBits.WriterThread, "Synch _sessionReset.WaitOne(done) PWM"); - - if (_isDisposed) break; - - TraceOutput(TraceBits.Synch | TraceBits.WriterThread, "Synch _sessionReset.Reset() PWM"); - _sessionReset.Reset(); - - // repeatedly write buffers as they become ready - WorkItem workitem = null; - Ionic.Zlib.CRC32 c= new Ionic.Zlib.CRC32(); - do - { - workitem = _pool[_nextToWrite % _pc]; - lock(workitem) - { - if (_noMoreInputForThisSegment) - TraceOutput(TraceBits.Write, - "Write drain wi({0}) stat({1}) canuse({2}) cba({3})", - workitem.index, - workitem.status, - (workitem.status == (int)WorkItem.Status.Compressed), - workitem.compressedBytesAvailable); - - do - { - if (workitem.status == (int)WorkItem.Status.Compressed) - { - TraceOutput(TraceBits.WriteBegin, - "Write begin wi({0}) stat({1}) cba({2})", - workitem.index, - workitem.status, - workitem.compressedBytesAvailable); - - workitem.status = (int)WorkItem.Status.Writing; - _outStream.Write(workitem.compressed, 0, workitem.compressedBytesAvailable); - c.Combine(workitem.crc, workitem.inputBytesAvailable); - _totalBytesProcessed += workitem.inputBytesAvailable; - _nextToWrite++; - workitem.inputBytesAvailable= 0; - workitem.status = (int)WorkItem.Status.Done; - - TraceOutput(TraceBits.WriteDone, - "Write done wi({0}) stat({1}) cba({2})", - workitem.index, - workitem.status, - workitem.compressedBytesAvailable); - - - Monitor.Pulse(workitem); - break; - } - else - { - int wcycles = 0; - // I've locked a workitem I cannot use. - // Therefore, wake someone else up, and then release the lock. - while (workitem.status != (int)WorkItem.Status.Compressed) - { - TraceOutput(TraceBits.WriteWait, - "Write waiting wi({0}) stat({1}) nw({2}) nf({3}) nomore({4})", - workitem.index, - workitem.status, - _nextToWrite, _nextToFill, - _noMoreInputForThisSegment ); - - if (_noMoreInputForThisSegment && _nextToWrite == _nextToFill) - break; - - wcycles++; - - // wake up someone else - Monitor.Pulse(workitem); - // release and wait - Monitor.Wait(workitem); - - if (workitem.status == (int)WorkItem.Status.Compressed) - TraceOutput(TraceBits.WriteWait, - "Write A-OK wi({0}) stat({1}) iba({2}) cba({3}) cyc({4})", - workitem.index, - workitem.status, - workitem.inputBytesAvailable, - workitem.compressedBytesAvailable, - wcycles); - } - - if (_noMoreInputForThisSegment && _nextToWrite == _nextToFill) - break; - - } - } - while (true); - } - - if (_noMoreInputForThisSegment) - TraceOutput(TraceBits.Write, - "Write nomore nw({0}) nf({1}) break({2})", - _nextToWrite, _nextToFill, (_nextToWrite == _nextToFill)); - - if (_noMoreInputForThisSegment && _nextToWrite == _nextToFill) - break; - - } while (true); - - - // Finish: - // After writing a series of buffers, closing each one with - // Flush.Sync, we now write the final one as Flush.Finish, and - // then stop. - byte[] buffer = new byte[128]; - ZlibCodec compressor = new ZlibCodec(); - int rc = compressor.InitializeDeflate(_compressLevel, false); - compressor.InputBuffer = null; - compressor.NextIn = 0; - compressor.AvailableBytesIn = 0; - compressor.OutputBuffer = buffer; - compressor.NextOut = 0; - compressor.AvailableBytesOut = buffer.Length; - rc = compressor.Deflate(FlushType.Finish); - - if (rc != ZlibConstants.Z_STREAM_END && rc != ZlibConstants.Z_OK) - throw new Exception("deflating: " + compressor.Message); - - if (buffer.Length - compressor.AvailableBytesOut > 0) - { - TraceOutput(TraceBits.WriteBegin, - "Write begin flush bytes({0})", - buffer.Length - compressor.AvailableBytesOut); - - _outStream.Write(buffer, 0, buffer.Length - compressor.AvailableBytesOut); - - TraceOutput(TraceBits.WriteBegin, - "Write done flush"); - } - - compressor.EndDeflate(); - - _Crc32 = c.Crc32Result; - - // signal that writing is complete: - TraceOutput(TraceBits.Synch, "Synch _writingDone.Set() PWM"); - _writingDone.Set(); - } - while (true); - } - catch (System.Exception exc1) - { - lock(_eLock) - { - // expose the exception to the main thread - if (_pendingException!=null) - _pendingException = exc1; - } - } - - TraceOutput(TraceBits.WriterThread, "_PerpetualWriterMethod FINIS"); - } -#endif - - - - - private void _DeflateOne(Object wi) - { - // compress one buffer - WorkItem workitem = (WorkItem) wi; - try - { - int myItem = workitem.index; - Ionic.Crc.CRC32 crc = new Ionic.Crc.CRC32(); - - // calc CRC on the buffer - crc.SlurpBlock(workitem.buffer, 0, workitem.inputBytesAvailable); - - // deflate it - DeflateOneSegment(workitem); - - // update status - workitem.crc = crc.Crc32Result; - TraceOutput(TraceBits.Compress, - "Compress wi({0}) ord({1}) len({2})", - workitem.index, - workitem.ordinal, - workitem.compressedBytesAvailable - ); - - lock(_latestLock) - { - if (workitem.ordinal > _latestCompressed) - _latestCompressed = workitem.ordinal; - } - lock (_toWrite) - { - _toWrite.Enqueue(workitem.index); - } - _newlyCompressedBlob.Set(); - } - catch (System.Exception exc1) - { - lock(_eLock) - { - // expose the exception to the main thread - if (_pendingException!=null) - _pendingException = exc1; - } - } - } - - - - - private bool DeflateOneSegment(WorkItem workitem) - { - ZlibCodec compressor = workitem.compressor; - int rc= 0; - compressor.ResetDeflate(); - compressor.NextIn = 0; - - compressor.AvailableBytesIn = workitem.inputBytesAvailable; - - // step 1: deflate the buffer - compressor.NextOut = 0; - compressor.AvailableBytesOut = workitem.compressed.Length; - do - { - compressor.Deflate(FlushType.None); - } - while (compressor.AvailableBytesIn > 0 || compressor.AvailableBytesOut == 0); - - // step 2: flush (sync) - rc = compressor.Deflate(FlushType.Sync); - - workitem.compressedBytesAvailable= (int) compressor.TotalBytesOut; - return true; - } - - - [System.Diagnostics.ConditionalAttribute("Trace")] - private void TraceOutput(TraceBits bits, string format, params object[] varParams) - { - if ((bits & _DesiredTrace) != 0) - { - lock(_outputLock) - { - int tid = Thread.CurrentThread.GetHashCode(); -#if !SILVERLIGHT - Console.ForegroundColor = (ConsoleColor) (tid % 8 + 8); -#endif - Console.Write("{0:000} PDOS ", tid); - Console.WriteLine(format, varParams); -#if !SILVERLIGHT - Console.ResetColor(); -#endif - } - } - } - - - // used only when Trace is defined - [Flags] - enum TraceBits : uint - { - None = 0, - NotUsed1 = 1, - EmitLock = 2, - EmitEnter = 4, // enter _EmitPending - EmitBegin = 8, // begin to write out - EmitDone = 16, // done writing out - EmitSkip = 32, // writer skipping a workitem - EmitAll = 58, // All Emit flags - Flush = 64, - Lifecycle = 128, // constructor/disposer - Session = 256, // Close/Reset - Synch = 512, // thread synchronization - Instance = 1024, // instance settings - Compress = 2048, // compress task - Write = 4096, // filling buffers, when caller invokes Write() - WriteEnter = 8192, // upon entry to Write() - WriteTake = 16384, // on _toFill.Take() - All = 0xffffffff, - } - - - - /// - /// Indicates whether the stream supports Seek operations. - /// - /// - /// Always returns false. - /// - public override bool CanSeek - { - get { return false; } - } - - - /// - /// Indicates whether the stream supports Read operations. - /// - /// - /// Always returns false. - /// - public override bool CanRead - { - get {return false;} - } - - /// - /// Indicates whether the stream supports Write operations. - /// - /// - /// Returns true if the provided stream is writable. - /// - public override bool CanWrite - { - get { return _outStream.CanWrite; } - } - - /// - /// Reading this property always throws a NotSupportedException. - /// - public override long Length - { - get { throw new NotSupportedException(); } - } - - /// - /// Returns the current position of the output stream. - /// - /// - /// - /// Because the output gets written by a background thread, - /// the value may change asynchronously. Setting this - /// property always throws a NotSupportedException. - /// - /// - public override long Position - { - get { return _outStream.Position; } - set { throw new NotSupportedException(); } - } - - /// - /// This method always throws a NotSupportedException. - /// - /// - /// The buffer into which data would be read, IF THIS METHOD - /// ACTUALLY DID ANYTHING. - /// - /// - /// The offset within that data array at which to insert the - /// data that is read, IF THIS METHOD ACTUALLY DID - /// ANYTHING. - /// - /// - /// The number of bytes to write, IF THIS METHOD ACTUALLY DID - /// ANYTHING. - /// - /// nothing. - public override int Read(byte[] buffer, int offset, int count) - { - throw new NotSupportedException(); - } - - /// - /// This method always throws a NotSupportedException. - /// - /// - /// The offset to seek to.... - /// IF THIS METHOD ACTUALLY DID ANYTHING. - /// - /// - /// The reference specifying how to apply the offset.... IF - /// THIS METHOD ACTUALLY DID ANYTHING. - /// - /// nothing. It always throws. - public override long Seek(long offset, System.IO.SeekOrigin origin) - { - throw new NotSupportedException(); - } - - /// - /// This method always throws a NotSupportedException. - /// - /// - /// The new value for the stream length.... IF - /// THIS METHOD ACTUALLY DID ANYTHING. - /// - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - } - -} - - diff --git a/MinecraftClient/Protocol/Handlers/Compression/Tree.cs b/MinecraftClient/Protocol/Handlers/Compression/Tree.cs deleted file mode 100644 index 1db8c4f4..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Tree.cs +++ /dev/null @@ -1,423 +0,0 @@ -// Tree.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation. -// 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: <2009-October-28 13:29:50> -// -// ------------------------------------------------------------------ -// -// This module defines classes for zlib compression and -// decompression. This code is derived from the jzlib implementation of -// zlib. In keeping with the license for jzlib, the copyright to that -// code is below. -// -// ------------------------------------------------------------------ -// -// Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in -// the documentation and/or other materials provided with the distribution. -// -// 3. The names of the authors may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -// INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// ----------------------------------------------------------------------- -// -// This program is based on zlib-1.1.3; credit to authors -// Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) -// and contributors of zlib. -// -// ----------------------------------------------------------------------- - - -using System; - -namespace Ionic.Zlib -{ - sealed class Tree - { - private static readonly int HEAP_SIZE = (2 * InternalConstants.L_CODES + 1); - - // extra bits for each length code - internal static readonly int[] ExtraLengthBits = new int[] - { - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 - }; - - // extra bits for each distance code - internal static readonly int[] ExtraDistanceBits = new int[] - { - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 - }; - - // extra bits for each bit length code - internal static readonly int[] extra_blbits = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7}; - - internal static readonly sbyte[] bl_order = new sbyte[]{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - - // The lengths of the bit length codes are sent in order of decreasing - // probability, to avoid transmitting the lengths for unused bit - // length codes. - - internal const int Buf_size = 8 * 2; - - // see definition of array dist_code below - //internal const int DIST_CODE_LEN = 512; - - private static readonly sbyte[] _dist_code = new sbyte[] - { - 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 0, 0, 16, 17, 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, - 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, - 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 - }; - - internal static readonly sbyte[] LengthCode = new sbyte[] - { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, - 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, - 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 - }; - - - internal static readonly int[] LengthBase = new int[] - { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, - 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 0 - }; - - - internal static readonly int[] DistanceBase = new int[] - { - 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, - 256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 - }; - - - /// - /// Map from a distance to a distance code. - /// - /// - /// No side effects. _dist_code[256] and _dist_code[257] are never used. - /// - internal static int DistanceCode(int dist) - { - return (dist < 256) - ? _dist_code[dist] - : _dist_code[256 + SharedUtils.URShift(dist, 7)]; - } - - internal short[] dyn_tree; // the dynamic tree - internal int max_code; // largest code with non zero frequency - internal StaticTree staticTree; // the corresponding static tree - - // Compute the optimal bit lengths for a tree and update the total bit length - // for the current block. - // IN assertion: the fields freq and dad are set, heap[heap_max] and - // above are the tree nodes sorted by increasing frequency. - // OUT assertions: the field len is set to the optimal bit length, the - // array bl_count contains the frequencies for each bit length. - // The length opt_len is updated; static_len is also updated if stree is - // not null. - internal void gen_bitlen(DeflateManager s) - { - short[] tree = dyn_tree; - short[] stree = staticTree.treeCodes; - int[] extra = staticTree.extraBits; - int base_Renamed = staticTree.extraBase; - int max_length = staticTree.maxLength; - int h; // heap index - int n, m; // iterate over the tree elements - int bits; // bit length - int xbits; // extra bits - short f; // frequency - int overflow = 0; // number of elements with bit length too large - - for (bits = 0; bits <= InternalConstants.MAX_BITS; bits++) - s.bl_count[bits] = 0; - - // In a first pass, compute the optimal bit lengths (which may - // overflow in the case of the bit length tree). - tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap - - for (h = s.heap_max + 1; h < HEAP_SIZE; h++) - { - n = s.heap[h]; - bits = tree[tree[n * 2 + 1] * 2 + 1] + 1; - if (bits > max_length) - { - bits = max_length; overflow++; - } - tree[n * 2 + 1] = (short) bits; - // We overwrite tree[n*2+1] which is no longer needed - - if (n > max_code) - continue; // not a leaf node - - s.bl_count[bits]++; - xbits = 0; - if (n >= base_Renamed) - xbits = extra[n - base_Renamed]; - f = tree[n * 2]; - s.opt_len += f * (bits + xbits); - if (stree != null) - s.static_len += f * (stree[n * 2 + 1] + xbits); - } - if (overflow == 0) - return ; - - // This happens for example on obj2 and pic of the Calgary corpus - // Find the first bit length which could increase: - do - { - bits = max_length - 1; - while (s.bl_count[bits] == 0) - bits--; - s.bl_count[bits]--; // move one leaf down the tree - s.bl_count[bits + 1] = (short) (s.bl_count[bits + 1] + 2); // move one overflow item as its brother - s.bl_count[max_length]--; - // The brother of the overflow item also moves one step up, - // but this does not affect bl_count[max_length] - overflow -= 2; - } - while (overflow > 0); - - for (bits = max_length; bits != 0; bits--) - { - n = s.bl_count[bits]; - while (n != 0) - { - m = s.heap[--h]; - if (m > max_code) - continue; - if (tree[m * 2 + 1] != bits) - { - s.opt_len = (int) (s.opt_len + ((long) bits - (long) tree[m * 2 + 1]) * (long) tree[m * 2]); - tree[m * 2 + 1] = (short) bits; - } - n--; - } - } - } - - // Construct one Huffman tree and assigns the code bit strings and lengths. - // Update the total bit length for the current block. - // IN assertion: the field freq is set for all tree elements. - // OUT assertions: the fields len and code are set to the optimal bit length - // and corresponding code. The length opt_len is updated; static_len is - // also updated if stree is not null. The field max_code is set. - internal void build_tree(DeflateManager s) - { - short[] tree = dyn_tree; - short[] stree = staticTree.treeCodes; - int elems = staticTree.elems; - int n, m; // iterate over heap elements - int max_code = -1; // largest code with non zero frequency - int node; // new node being created - - // Construct the initial heap, with least frequent element in - // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. - // heap[0] is not used. - s.heap_len = 0; - s.heap_max = HEAP_SIZE; - - for (n = 0; n < elems; n++) - { - if (tree[n * 2] != 0) - { - s.heap[++s.heap_len] = max_code = n; - s.depth[n] = 0; - } - else - { - tree[n * 2 + 1] = 0; - } - } - - // The pkzip format requires that at least one distance code exists, - // and that at least one bit should be sent even if there is only one - // possible code. So to avoid special checks later on we force at least - // two codes of non zero frequency. - while (s.heap_len < 2) - { - node = s.heap[++s.heap_len] = (max_code < 2?++max_code:0); - tree[node * 2] = 1; - s.depth[node] = 0; - s.opt_len--; - if (stree != null) - s.static_len -= stree[node * 2 + 1]; - // node is 0 or 1 so it does not have extra bits - } - this.max_code = max_code; - - // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, - // establish sub-heaps of increasing lengths: - - for (n = s.heap_len / 2; n >= 1; n--) - s.pqdownheap(tree, n); - - // Construct the Huffman tree by repeatedly combining the least two - // frequent nodes. - - node = elems; // next internal node of the tree - do - { - // n = node of least frequency - n = s.heap[1]; - s.heap[1] = s.heap[s.heap_len--]; - s.pqdownheap(tree, 1); - m = s.heap[1]; // m = node of next least frequency - - s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency - s.heap[--s.heap_max] = m; - - // Create a new node father of n and m - tree[node * 2] = unchecked((short) (tree[n * 2] + tree[m * 2])); - s.depth[node] = (sbyte) (System.Math.Max((byte) s.depth[n], (byte) s.depth[m]) + 1); - tree[n * 2 + 1] = tree[m * 2 + 1] = (short) node; - - // and insert the new node in the heap - s.heap[1] = node++; - s.pqdownheap(tree, 1); - } - while (s.heap_len >= 2); - - s.heap[--s.heap_max] = s.heap[1]; - - // At this point, the fields freq and dad are set. We can now - // generate the bit lengths. - - gen_bitlen(s); - - // The field len is now set, we can generate the bit codes - gen_codes(tree, max_code, s.bl_count); - } - - // Generate the codes for a given tree and bit counts (which need not be - // optimal). - // IN assertion: the array bl_count contains the bit length statistics for - // the given tree and the field len is set for all tree elements. - // OUT assertion: the field code is set for all tree elements of non - // zero code length. - internal static void gen_codes(short[] tree, int max_code, short[] bl_count) - { - short[] next_code = new short[InternalConstants.MAX_BITS + 1]; // next code value for each bit length - short code = 0; // running code value - int bits; // bit index - int n; // code index - - // The distribution counts are first used to generate the code values - // without bit reversal. - for (bits = 1; bits <= InternalConstants.MAX_BITS; bits++) - unchecked { - next_code[bits] = code = (short) ((code + bl_count[bits - 1]) << 1); - } - - // Check that the bit counts in bl_count are consistent. The last code - // must be all ones. - //Assert (code + bl_count[MAX_BITS]-1 == (1<>= 1; //SharedUtils.URShift(code, 1); - res <<= 1; - } - while (--len > 0); - return res >> 1; - } - } -} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ComHelper.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ComHelper.cs deleted file mode 100644 index 385cef27..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ComHelper.cs +++ /dev/null @@ -1,116 +0,0 @@ -// ComHelper.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2009 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-June-13 17:04:06> -// -// ------------------------------------------------------------------ -// -// This module defines a COM Helper class. -// -// Created: Tue, 08 Sep 2009 22:03 -// - -using Interop=System.Runtime.InteropServices; - -namespace Ionic.Zip -{ - /// - /// This class exposes a set of COM-accessible wrappers for static - /// methods available on the ZipFile class. You don't need this - /// class unless you are using DotNetZip from a COM environment. - /// - [System.Runtime.InteropServices.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d0000F")] - [System.Runtime.InteropServices.ComVisible(true)] -#if !NETCF - [System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.AutoDispatch)] -#endif - - public class ComHelper - { - /// - /// A wrapper for ZipFile.IsZipFile(string) - /// - /// The filename to of the zip file to check. - /// true if the file contains a valid zip file. - public bool IsZipFile(string filename) - { - return ZipFile.IsZipFile(filename); - } - - /// - /// A wrapper for ZipFile.IsZipFile(string, bool) - /// - /// - /// We cannot use "overloaded" Method names in COM interop. - /// So, here, we use a unique name. - /// - /// The filename to of the zip file to check. - /// true if the file contains a valid zip file. - public bool IsZipFileWithExtract(string filename) - { - return ZipFile.IsZipFile(filename, true); - } - -#if !NETCF - /// - /// A wrapper for ZipFile.CheckZip(string) - /// - /// The filename to of the zip file to check. - /// - /// true if the named zip file checks OK. Otherwise, false. - public bool CheckZip(string filename) - { - return ZipFile.CheckZip(filename); - } - - /// - /// A COM-friendly wrapper for the static method . - /// - /// - /// The filename to of the zip file to check. - /// - /// The password to check. - /// - /// true if the named zip file checks OK. Otherwise, false. - public bool CheckZipPassword(string filename, string password) - { - return ZipFile.CheckZipPassword(filename, password); - } - - /// - /// A wrapper for ZipFile.FixZipDirectory(string) - /// - /// The filename to of the zip file to fix. - public void FixZipDirectory(string filename) - { - ZipFile.FixZipDirectory(filename); - } -#endif - - /// - /// A wrapper for ZipFile.LibraryVersion - /// - /// - /// the version number on the DotNetZip assembly, formatted as a string. - /// - public string GetZipLibraryVersion() - { - return ZipFile.LibraryVersion.ToString(); - } - - } -} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/EncryptionAlgorithm.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/EncryptionAlgorithm.cs deleted file mode 100644 index 66b4f40f..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/EncryptionAlgorithm.cs +++ /dev/null @@ -1,135 +0,0 @@ -// EncryptionAlgorithm.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2009 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: <2009-October-21 17:24:45> -// -// ------------------------------------------------------------------ -// -// This module defines the EncryptionAgorithm enum -// -// -// ------------------------------------------------------------------ - - -namespace Ionic.Zip -{ - /// - /// An enum that provides the various encryption algorithms supported by this - /// library. - /// - /// - /// - /// - /// - /// PkzipWeak implies the use of Zip 2.0 encryption, which is known to be - /// weak and subvertible. - /// - /// - /// - /// A note on interoperability: Values of PkzipWeak and None are - /// specified in PKWARE's zip - /// specification, and are considered to be "standard". Zip archives - /// produced using these options will be interoperable with many other zip tools - /// and libraries, including Windows Explorer. - /// - /// - /// - /// Values of WinZipAes128 and WinZipAes256 are not part of the Zip - /// specification, but rather imply the use of a vendor-specific extension from - /// WinZip. If you want to produce interoperable Zip archives, do not use these - /// values. For example, if you produce a zip archive using WinZipAes256, you - /// will be able to open it in Windows Explorer on Windows XP and Vista, but you - /// will not be able to extract entries; trying this will lead to an "unspecified - /// error". For this reason, some people have said that a zip archive that uses - /// WinZip's AES encryption is not actually a zip archive at all. A zip archive - /// produced this way will be readable with the WinZip tool (Version 11 and - /// beyond). - /// - /// - /// - /// There are other third-party tools and libraries, both commercial and - /// otherwise, that support WinZip's AES encryption. These will be able to read - /// AES-encrypted zip archives produced by DotNetZip, and conversely applications - /// that use DotNetZip to read zip archives will be able to read AES-encrypted - /// archives produced by those tools or libraries. Consult the documentation for - /// those other tools and libraries to find out if WinZip's AES encryption is - /// supported. - /// - /// - /// - /// In case you care: According to the WinZip specification, the - /// actual AES key used is derived from the via an - /// algorithm that complies with RFC 2898, using an iteration - /// count of 1000. The algorithm is sometimes referred to as PBKDF2, which stands - /// for "Password Based Key Derivation Function #2". - /// - /// - /// - /// A word about password strength and length: The AES encryption technology is - /// very good, but any system is only as secure as the weakest link. If you want - /// to secure your data, be sure to use a password that is hard to guess. To make - /// it harder to guess (increase its "entropy"), you should make it longer. If - /// you use normal characters from an ASCII keyboard, a password of length 20 will - /// be strong enough that it will be impossible to guess. For more information on - /// that, I'd encourage you to read this - /// article. - /// - /// - /// - /// The WinZip AES algorithms are not supported with the version of DotNetZip that - /// runs on the .NET Compact Framework. This is because .NET CF lacks the - /// HMACSHA1 class that is required for producing the archive. - /// - /// - public enum EncryptionAlgorithm - { - /// - /// No encryption at all. - /// - None = 0, - - /// - /// Traditional or Classic pkzip encryption. - /// - PkzipWeak, - -#if AESCRYPTO - /// - /// WinZip AES encryption (128 key bits). - /// - WinZipAes128, - - /// - /// WinZip AES encryption (256 key bits). - /// - WinZipAes256, -#endif - - /// - /// An encryption algorithm that is not supported by DotNetZip. - /// - Unsupported = 4, - - - // others... not implemented (yet?) - } - -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/Events.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/Events.cs deleted file mode 100644 index e51ff78f..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/Events.cs +++ /dev/null @@ -1,684 +0,0 @@ -// Events.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2006, 2007, 2008, 2009 Dino Chiesa and Microsoft Corporation. -// 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-August-06 12:26:24> -// -// ------------------------------------------------------------------ -// -// This module defines events used by the ZipFile class. -// -// - -using System; -using System.Collections.Generic; -using System.Text; - -namespace Ionic.Zip -{ - /// - /// Delegate in which the application writes the ZipEntry content for the named entry. - /// - /// - /// The name of the entry that must be written. - /// The stream to which the entry data should be written. - /// - /// - /// When you add an entry and specify a WriteDelegate, via , the application - /// code provides the logic that writes the entry data directly into the zip file. - /// - /// - /// - /// - /// This example shows how to define a WriteDelegate that obtains a DataSet, and then - /// writes the XML for the DataSet into the zip archive. There's no need to - /// save the XML to a disk file first. - /// - /// - /// private void WriteEntry (String filename, Stream output) - /// { - /// DataSet ds1 = ObtainDataSet(); - /// ds1.WriteXml(output); - /// } - /// - /// private void Run() - /// { - /// using (var zip = new ZipFile()) - /// { - /// zip.AddEntry(zipEntryName, WriteEntry); - /// zip.Save(zipFileName); - /// } - /// } - /// - /// - /// - /// Private Sub WriteEntry (ByVal filename As String, ByVal output As Stream) - /// DataSet ds1 = ObtainDataSet() - /// ds1.WriteXml(stream) - /// End Sub - /// - /// Public Sub Run() - /// Using zip = New ZipFile - /// zip.AddEntry(zipEntryName, New WriteDelegate(AddressOf WriteEntry)) - /// zip.Save(zipFileName) - /// End Using - /// End Sub - /// - /// - /// - public delegate void WriteDelegate(string entryName, System.IO.Stream stream); - - - /// - /// Delegate in which the application opens the stream, just-in-time, for the named entry. - /// - /// - /// - /// The name of the ZipEntry that the application should open the stream for. - /// - /// - /// - /// When you add an entry via , the application code provides the logic that - /// opens and closes the stream for the given ZipEntry. - /// - /// - /// - public delegate System.IO.Stream OpenDelegate(string entryName); - - /// - /// Delegate in which the application closes the stream, just-in-time, for the named entry. - /// - /// - /// - /// The name of the ZipEntry that the application should close the stream for. - /// - /// - /// The stream to be closed. - /// - /// - /// When you add an entry via , the application code provides the logic that - /// opens and closes the stream for the given ZipEntry. - /// - /// - /// - public delegate void CloseDelegate(string entryName, System.IO.Stream stream); - - /// - /// Delegate for the callback by which the application tells the - /// library the CompressionLevel to use for a file. - /// - /// - /// - /// - /// Using this callback, the application can, for example, specify that - /// previously-compressed files (.mp3, .png, .docx, etc) should use a - /// CompressionLevel of None, or can set the compression level based - /// on any other factor. - /// - /// - /// - public delegate Ionic.Zlib.CompressionLevel SetCompressionCallback(string localFileName, string fileNameInArchive); - - /// - /// In an EventArgs type, indicates which sort of progress event is being - /// reported. - /// - /// - /// There are events for reading, events for saving, and events for - /// extracting. This enumeration allows a single EventArgs type to be sued to - /// describe one of multiple subevents. For example, a SaveProgress event is - /// invoked before, after, and during the saving of a single entry. The value - /// of an enum with this type, specifies which event is being triggered. The - /// same applies to Extraction, Reading and Adding events. - /// - public enum ZipProgressEventType - { - /// - /// Indicates that a Add() operation has started. - /// - Adding_Started, - - /// - /// Indicates that an individual entry in the archive has been added. - /// - Adding_AfterAddEntry, - - /// - /// Indicates that a Add() operation has completed. - /// - Adding_Completed, - - /// - /// Indicates that a Read() operation has started. - /// - Reading_Started, - - /// - /// Indicates that an individual entry in the archive is about to be read. - /// - Reading_BeforeReadEntry, - - /// - /// Indicates that an individual entry in the archive has just been read. - /// - Reading_AfterReadEntry, - - /// - /// Indicates that a Read() operation has completed. - /// - Reading_Completed, - - /// - /// The given event reports the number of bytes read so far - /// during a Read() operation. - /// - Reading_ArchiveBytesRead, - - /// - /// Indicates that a Save() operation has started. - /// - Saving_Started, - - /// - /// Indicates that an individual entry in the archive is about to be written. - /// - Saving_BeforeWriteEntry, - - /// - /// Indicates that an individual entry in the archive has just been saved. - /// - Saving_AfterWriteEntry, - - /// - /// Indicates that a Save() operation has completed. - /// - Saving_Completed, - - /// - /// Indicates that the zip archive has been created in a - /// temporary location during a Save() operation. - /// - Saving_AfterSaveTempArchive, - - /// - /// Indicates that the temporary file is about to be renamed to the final archive - /// name during a Save() operation. - /// - Saving_BeforeRenameTempArchive, - - /// - /// Indicates that the temporary file is has just been renamed to the final archive - /// name during a Save() operation. - /// - Saving_AfterRenameTempArchive, - - /// - /// Indicates that the self-extracting archive has been compiled - /// during a Save() operation. - /// - Saving_AfterCompileSelfExtractor, - - /// - /// The given event is reporting the number of source bytes that have run through the compressor so far - /// during a Save() operation. - /// - Saving_EntryBytesRead, - - /// - /// Indicates that an entry is about to be extracted. - /// - Extracting_BeforeExtractEntry, - - /// - /// Indicates that an entry has just been extracted. - /// - Extracting_AfterExtractEntry, - - /// - /// Indicates that extraction of an entry would overwrite an existing - /// filesystem file. You must use - /// - /// ExtractExistingFileAction.InvokeExtractProgressEvent in the call - /// to ZipEntry.Extract() in order to receive this event. - /// - Extracting_ExtractEntryWouldOverwrite, - - /// - /// The given event is reporting the number of bytes written so far for - /// the current entry during an Extract() operation. - /// - Extracting_EntryBytesWritten, - - /// - /// Indicates that an ExtractAll operation is about to begin. - /// - Extracting_BeforeExtractAll, - - /// - /// Indicates that an ExtractAll operation has completed. - /// - Extracting_AfterExtractAll, - - /// - /// Indicates that an error has occurred while saving a zip file. - /// This generally means the file cannot be opened, because it has been - /// removed, or because it is locked by another process. It can also - /// mean that the file cannot be Read, because of a range lock conflict. - /// - Error_Saving, - } - - - /// - /// Provides information about the progress of a save, read, or extract operation. - /// This is a base class; you will probably use one of the classes derived from this one. - /// - public class ZipProgressEventArgs : EventArgs - { - private int _entriesTotal; - private bool _cancel; - private ZipEntry _latestEntry; - private ZipProgressEventType _flavor; - private String _archiveName; - private Int64 _bytesTransferred; - private Int64 _totalBytesToTransfer; - - - internal ZipProgressEventArgs() { } - - internal ZipProgressEventArgs(string archiveName, ZipProgressEventType flavor) - { - this._archiveName = archiveName; - this._flavor = flavor; - } - - /// - /// The total number of entries to be saved or extracted. - /// - public int EntriesTotal - { - get { return _entriesTotal; } - set { _entriesTotal = value; } - } - - /// - /// The name of the last entry saved or extracted. - /// - public ZipEntry CurrentEntry - { - get { return _latestEntry; } - set { _latestEntry = value; } - } - - /// - /// In an event handler, set this to cancel the save or extract - /// operation that is in progress. - /// - public bool Cancel - { - get { return _cancel; } - set { _cancel = _cancel || value; } - } - - /// - /// The type of event being reported. - /// - public ZipProgressEventType EventType - { - get { return _flavor; } - set { _flavor = value; } - } - - /// - /// Returns the archive name associated to this event. - /// - public String ArchiveName - { - get { return _archiveName; } - set { _archiveName = value; } - } - - - /// - /// The number of bytes read or written so far for this entry. - /// - public Int64 BytesTransferred - { - get { return _bytesTransferred; } - set { _bytesTransferred = value; } - } - - - - /// - /// Total number of bytes that will be read or written for this entry. - /// This number will be -1 if the value cannot be determined. - /// - public Int64 TotalBytesToTransfer - { - get { return _totalBytesToTransfer; } - set { _totalBytesToTransfer = value; } - } - } - - - - /// - /// Provides information about the progress of a Read operation. - /// - public class ReadProgressEventArgs : ZipProgressEventArgs - { - - internal ReadProgressEventArgs() { } - - private ReadProgressEventArgs(string archiveName, ZipProgressEventType flavor) - : base(archiveName, flavor) - { } - - internal static ReadProgressEventArgs Before(string archiveName, int entriesTotal) - { - var x = new ReadProgressEventArgs(archiveName, ZipProgressEventType.Reading_BeforeReadEntry); - x.EntriesTotal = entriesTotal; - return x; - } - - internal static ReadProgressEventArgs After(string archiveName, ZipEntry entry, int entriesTotal) - { - var x = new ReadProgressEventArgs(archiveName, ZipProgressEventType.Reading_AfterReadEntry); - x.EntriesTotal = entriesTotal; - x.CurrentEntry = entry; - return x; - } - - internal static ReadProgressEventArgs Started(string archiveName) - { - var x = new ReadProgressEventArgs(archiveName, ZipProgressEventType.Reading_Started); - return x; - } - - internal static ReadProgressEventArgs ByteUpdate(string archiveName, ZipEntry entry, Int64 bytesXferred, Int64 totalBytes) - { - var x = new ReadProgressEventArgs(archiveName, ZipProgressEventType.Reading_ArchiveBytesRead); - x.CurrentEntry = entry; - x.BytesTransferred = bytesXferred; - x.TotalBytesToTransfer = totalBytes; - return x; - } - - internal static ReadProgressEventArgs Completed(string archiveName) - { - var x = new ReadProgressEventArgs(archiveName, ZipProgressEventType.Reading_Completed); - return x; - } - - } - - - /// - /// Provides information about the progress of a Add operation. - /// - public class AddProgressEventArgs : ZipProgressEventArgs - { - internal AddProgressEventArgs() { } - - private AddProgressEventArgs(string archiveName, ZipProgressEventType flavor) - : base(archiveName, flavor) - { } - - internal static AddProgressEventArgs AfterEntry(string archiveName, ZipEntry entry, int entriesTotal) - { - var x = new AddProgressEventArgs(archiveName, ZipProgressEventType.Adding_AfterAddEntry); - x.EntriesTotal = entriesTotal; - x.CurrentEntry = entry; - return x; - } - - internal static AddProgressEventArgs Started(string archiveName) - { - var x = new AddProgressEventArgs(archiveName, ZipProgressEventType.Adding_Started); - return x; - } - - internal static AddProgressEventArgs Completed(string archiveName) - { - var x = new AddProgressEventArgs(archiveName, ZipProgressEventType.Adding_Completed); - return x; - } - - } - - /// - /// Provides information about the progress of a save operation. - /// - public class SaveProgressEventArgs : ZipProgressEventArgs - { - private int _entriesSaved; - - /// - /// Constructor for the SaveProgressEventArgs. - /// - /// the name of the zip archive. - /// whether this is before saving the entry, or after - /// The total number of entries in the zip archive. - /// Number of entries that have been saved. - /// The entry involved in the event. - internal SaveProgressEventArgs(string archiveName, bool before, int entriesTotal, int entriesSaved, ZipEntry entry) - : base(archiveName, (before) ? ZipProgressEventType.Saving_BeforeWriteEntry : ZipProgressEventType.Saving_AfterWriteEntry) - { - this.EntriesTotal = entriesTotal; - this.CurrentEntry = entry; - this._entriesSaved = entriesSaved; - } - - internal SaveProgressEventArgs() { } - - internal SaveProgressEventArgs(string archiveName, ZipProgressEventType flavor) - : base(archiveName, flavor) - { } - - - internal static SaveProgressEventArgs ByteUpdate(string archiveName, ZipEntry entry, Int64 bytesXferred, Int64 totalBytes) - { - var x = new SaveProgressEventArgs(archiveName, ZipProgressEventType.Saving_EntryBytesRead); - x.ArchiveName = archiveName; - x.CurrentEntry = entry; - x.BytesTransferred = bytesXferred; - x.TotalBytesToTransfer = totalBytes; - return x; - } - - internal static SaveProgressEventArgs Started(string archiveName) - { - var x = new SaveProgressEventArgs(archiveName, ZipProgressEventType.Saving_Started); - return x; - } - - internal static SaveProgressEventArgs Completed(string archiveName) - { - var x = new SaveProgressEventArgs(archiveName, ZipProgressEventType.Saving_Completed); - return x; - } - - /// - /// Number of entries saved so far. - /// - public int EntriesSaved - { - get { return _entriesSaved; } - } - } - - - /// - /// Provides information about the progress of the extract operation. - /// - public class ExtractProgressEventArgs : ZipProgressEventArgs - { - private int _entriesExtracted; - private string _target; - - /// - /// Constructor for the ExtractProgressEventArgs. - /// - /// the name of the zip archive. - /// whether this is before saving the entry, or after - /// The total number of entries in the zip archive. - /// Number of entries that have been extracted. - /// The entry involved in the event. - /// The location to which entries are extracted. - internal ExtractProgressEventArgs(string archiveName, bool before, int entriesTotal, int entriesExtracted, ZipEntry entry, string extractLocation) - : base(archiveName, (before) ? ZipProgressEventType.Extracting_BeforeExtractEntry : ZipProgressEventType.Extracting_AfterExtractEntry) - { - this.EntriesTotal = entriesTotal; - this.CurrentEntry = entry; - this._entriesExtracted = entriesExtracted; - this._target = extractLocation; - } - - internal ExtractProgressEventArgs(string archiveName, ZipProgressEventType flavor) - : base(archiveName, flavor) - { } - - internal ExtractProgressEventArgs() - { } - - - internal static ExtractProgressEventArgs BeforeExtractEntry(string archiveName, ZipEntry entry, string extractLocation) - { - var x = new ExtractProgressEventArgs - { - ArchiveName = archiveName, - EventType = ZipProgressEventType.Extracting_BeforeExtractEntry, - CurrentEntry = entry, - _target = extractLocation, - }; - return x; - } - - internal static ExtractProgressEventArgs ExtractExisting(string archiveName, ZipEntry entry, string extractLocation) - { - var x = new ExtractProgressEventArgs - { - ArchiveName = archiveName, - EventType = ZipProgressEventType.Extracting_ExtractEntryWouldOverwrite, - CurrentEntry = entry, - _target = extractLocation, - }; - return x; - } - - internal static ExtractProgressEventArgs AfterExtractEntry(string archiveName, ZipEntry entry, string extractLocation) - { - var x = new ExtractProgressEventArgs - { - ArchiveName = archiveName, - EventType = ZipProgressEventType.Extracting_AfterExtractEntry, - CurrentEntry = entry, - _target = extractLocation, - }; - return x; - } - - internal static ExtractProgressEventArgs ExtractAllStarted(string archiveName, string extractLocation) - { - var x = new ExtractProgressEventArgs(archiveName, ZipProgressEventType.Extracting_BeforeExtractAll); - x._target = extractLocation; - return x; - } - - internal static ExtractProgressEventArgs ExtractAllCompleted(string archiveName, string extractLocation) - { - var x = new ExtractProgressEventArgs(archiveName, ZipProgressEventType.Extracting_AfterExtractAll); - x._target = extractLocation; - return x; - } - - - internal static ExtractProgressEventArgs ByteUpdate(string archiveName, ZipEntry entry, Int64 bytesWritten, Int64 totalBytes) - { - var x = new ExtractProgressEventArgs(archiveName, ZipProgressEventType.Extracting_EntryBytesWritten); - x.ArchiveName = archiveName; - x.CurrentEntry = entry; - x.BytesTransferred = bytesWritten; - x.TotalBytesToTransfer = totalBytes; - return x; - } - - - - /// - /// Number of entries extracted so far. This is set only if the - /// EventType is Extracting_BeforeExtractEntry or Extracting_AfterExtractEntry, and - /// the Extract() is occurring witin the scope of a call to ExtractAll(). - /// - public int EntriesExtracted - { - get { return _entriesExtracted; } - } - - /// - /// Returns the extraction target location, a filesystem path. - /// - public String ExtractLocation - { - get { return _target; } - } - - } - - - - /// - /// Provides information about the an error that occurred while zipping. - /// - public class ZipErrorEventArgs : ZipProgressEventArgs - { - private Exception _exc; - private ZipErrorEventArgs() { } - internal static ZipErrorEventArgs Saving(string archiveName, ZipEntry entry, Exception exception) - { - var x = new ZipErrorEventArgs - { - EventType = ZipProgressEventType.Error_Saving, - ArchiveName = archiveName, - CurrentEntry = entry, - _exc = exception - }; - return x; - } - - /// - /// Returns the exception that occurred, if any. - /// - public Exception @Exception - { - get { return _exc; } - } - - /// - /// Returns the name of the file that caused the exception, if any. - /// - public String FileName - { - get { return CurrentEntry.LocalFileName; } - } - } - - -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/Exceptions.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/Exceptions.cs deleted file mode 100644 index 9f67077e..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/Exceptions.cs +++ /dev/null @@ -1,300 +0,0 @@ -// Exceptions.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2008, 2009 Dino Chiesa and Microsoft Corporation. -// 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-12 12:19:10> -// -// ------------------------------------------------------------------ -// -// This module defines exceptions used in the class library. -// - - - -using System; -using System.Collections.Generic; -using System.Text; -#if !NETCF -using System.Runtime.Serialization; -#endif - -namespace Ionic.Zip -{ - ///// - ///// Base exception type for all custom exceptions in the Zip library. It acts as a marker class. - ///// - //[AttributeUsage(AttributeTargets.Class)] - //public class ZipExceptionAttribute : Attribute { } - - - - /// - /// Issued when an ZipEntry.ExtractWithPassword() method is invoked - /// with an incorrect password. - /// -#if !SILVERLIGHT - [Serializable] -#endif - [System.Runtime.InteropServices.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d0000B")] - public class BadPasswordException : ZipException - { - /// - /// Default ctor. - /// - public BadPasswordException() { } - - /// - /// Come on, you know how exceptions work. Why are you looking at this documentation? - /// - /// The message in the exception. - public BadPasswordException(String message) - : base(message) - { } - - /// - /// Come on, you know how exceptions work. Why are you looking at this documentation? - /// - /// The message in the exception. - /// The innerException for this exception. - public BadPasswordException(String message, Exception innerException) - : base(message, innerException) - { - } - - -#if ! (NETCF || SILVERLIGHT) - /// - /// Come on, you know how exceptions work. Why are you looking at this documentation? - /// - /// The serialization info for the exception. - /// The streaming context from which to deserialize. - protected BadPasswordException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } -#endif - - } - - /// - /// Indicates that a read was attempted on a stream, and bad or incomplete data was - /// received. - /// -#if !SILVERLIGHT - [Serializable] -#endif - [System.Runtime.InteropServices.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d0000A")] - public class BadReadException : ZipException - { - /// - /// Default ctor. - /// - public BadReadException() { } - - /// - /// Come on, you know how exceptions work. Why are you looking at this documentation? - /// - /// The message in the exception. - public BadReadException(String message) - : base(message) - { } - - /// - /// Come on, you know how exceptions work. Why are you looking at this documentation? - /// - /// The message in the exception. - /// The innerException for this exception. - public BadReadException(String message, Exception innerException) - : base(message, innerException) - { - } - -#if ! (NETCF || SILVERLIGHT) - /// - /// Come on, you know how exceptions work. Why are you looking at this documentation? - /// - /// The serialization info for the exception. - /// The streaming context from which to deserialize. - protected BadReadException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } -#endif - - } - - - - /// - /// Issued when an CRC check fails upon extracting an entry from a zip archive. - /// -#if !SILVERLIGHT - [Serializable] -#endif - [System.Runtime.InteropServices.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d00009")] - public class BadCrcException : ZipException - { - /// - /// Default ctor. - /// - public BadCrcException() { } - - /// - /// Come on, you know how exceptions work. Why are you looking at this documentation? - /// - /// The message in the exception. - public BadCrcException(String message) - : base(message) - { } - - -#if ! (NETCF || SILVERLIGHT) - /// - /// Come on, you know how exceptions work. Why are you looking at this documentation? - /// - /// The serialization info for the exception. - /// The streaming context from which to deserialize. - protected BadCrcException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } -#endif - - } - - - /// - /// Issued when errors occur saving a self-extracting archive. - /// -#if !SILVERLIGHT - [Serializable] -#endif - [System.Runtime.InteropServices.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d00008")] - public class SfxGenerationException : ZipException - { - /// - /// Default ctor. - /// - public SfxGenerationException() { } - - /// - /// Come on, you know how exceptions work. Why are you looking at this documentation? - /// - /// The message in the exception. - public SfxGenerationException(String message) - : base(message) - { } - -#if ! (NETCF || SILVERLIGHT) - /// - /// Come on, you know how exceptions work. Why are you looking at this documentation? - /// - /// The serialization info for the exception. - /// The streaming context from which to deserialize. - protected SfxGenerationException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } -#endif - - } - - - /// - /// Indicates that an operation was attempted on a ZipFile which was not possible - /// given the state of the instance. For example, if you call Save() on a ZipFile - /// which has no filename set, you can get this exception. - /// -#if !SILVERLIGHT - [Serializable] -#endif - [System.Runtime.InteropServices.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d00007")] - public class BadStateException : ZipException - { - /// - /// Default ctor. - /// - public BadStateException() { } - - /// - /// Come on, you know how exceptions work. Why are you looking at this documentation? - /// - /// The message in the exception. - public BadStateException(String message) - : base(message) - { } - - /// - /// Come on, you know how exceptions work. Why are you looking at this documentation? - /// - /// The message in the exception. - /// The innerException for this exception. - public BadStateException(String message, Exception innerException) - : base(message, innerException) - {} - -#if ! (NETCF || SILVERLIGHT) - /// - /// Come on, you know how exceptions work. Why are you looking at this documentation? - /// - /// The serialization info for the exception. - /// The streaming context from which to deserialize. - protected BadStateException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } -#endif - - } - - /// - /// Base class for all exceptions defined by and throw by the Zip library. - /// -#if !SILVERLIGHT - [Serializable] -#endif - [System.Runtime.InteropServices.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d00006")] - public class ZipException : Exception - { - /// - /// Default ctor. - /// - public ZipException() { } - - /// - /// Come on, you know how exceptions work. Why are you looking at this documentation? - /// - /// The message in the exception. - public ZipException(String message) : base(message) { } - - /// - /// Come on, you know how exceptions work. Why are you looking at this documentation? - /// - /// The message in the exception. - /// The innerException for this exception. - public ZipException(String message, Exception innerException) - : base(message, innerException) - { } - -#if ! (NETCF || SILVERLIGHT) - /// - /// Come on, you know how exceptions work. Why are you looking at this documentation? - /// - /// The serialization info for the exception. - /// The streaming context from which to deserialize. - protected ZipException(SerializationInfo info, StreamingContext context) - : base(info, context) - { } -#endif - - } - -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ExtractExistingFileAction.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ExtractExistingFileAction.cs deleted file mode 100644 index 2de229fd..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ExtractExistingFileAction.cs +++ /dev/null @@ -1,85 +0,0 @@ -// ExtractExistingFileAction.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2009 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: <2009-August-25 08:44:37> -// -// ------------------------------------------------------------------ -// -// This module defines the ExtractExistingFileAction enum -// -// -// ------------------------------------------------------------------ - - -namespace Ionic.Zip -{ - - /// - /// An enum for the options when extracting an entry would overwrite an existing file. - /// - /// - /// - /// - /// This enum describes the actions that the library can take when an - /// Extract() or ExtractWithPassword() method is called to extract an - /// entry to a filesystem, and the extraction would overwrite an existing filesystem - /// file. - /// - /// - /// - public enum ExtractExistingFileAction - { - /// - /// Throw an exception when extraction would overwrite an existing file. (For - /// COM clients, this is a 0 (zero).) - /// - Throw, - - /// - /// When extraction would overwrite an existing file, overwrite the file silently. - /// The overwrite will happen even if the target file is marked as read-only. - /// (For COM clients, this is a 1.) - /// - OverwriteSilently, - - /// - /// When extraction would overwrite an existing file, don't overwrite the file, silently. - /// (For COM clients, this is a 2.) - /// - DoNotOverwrite, - - /// - /// When extraction would overwrite an existing file, invoke the ExtractProgress - /// event, using an event type of . In - /// this way, the application can decide, just-in-time, whether to overwrite the - /// file. For example, a GUI application may wish to pop up a dialog to allow - /// the user to choose. You may want to examine the property before making - /// the decision. If, after your processing in the Extract progress event, you - /// want to NOT extract the file, set - /// on the ZipProgressEventArgs.CurrentEntry to DoNotOverwrite. - /// If you do want to extract the file, set ZipEntry.ExtractExistingFile - /// to OverwriteSilently. If you want to cancel the Extraction, set - /// ZipProgressEventArgs.Cancel to true. Cancelling differs from using - /// DoNotOverwrite in that a cancel will not extract any further entries, if - /// there are any. (For COM clients, the value of this enum is a 3.) - /// - InvokeExtractProgressEvent, - } - -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/FileSelector.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/FileSelector.cs deleted file mode 100644 index 874eb1b5..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/FileSelector.cs +++ /dev/null @@ -1,1608 +0,0 @@ -//#define SelectorTrace - -// FileSelector.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2008-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: <2011-August-05 11:03:11> -// -// ------------------------------------------------------------------ -// -// This module implements a "file selector" that finds files based on a -// set of inclusion criteria, including filename, size, file time, and -// potentially file attributes. The criteria are given in a string with -// a simple expression language. Examples: -// -// find all .txt files: -// name = *.txt -// -// shorthand for the above -// *.txt -// -// all files modified after January 1st, 2009 -// mtime > 2009-01-01 -// -// All .txt files modified after the first of the year -// name = *.txt AND mtime > 2009-01-01 -// -// All .txt files modified after the first of the year, or any file with the archive bit set -// (name = *.txt AND mtime > 2009-01-01) or (attribtues = A) -// -// All .txt files or any file greater than 1mb in size -// (name = *.txt or size > 1mb) -// -// and so on. -// ------------------------------------------------------------------ - - -using System; -using System.IO; -using System.Text; -using System.Reflection; -using System.ComponentModel; -using System.Text.RegularExpressions; -using System.Collections.Generic; -#if SILVERLIGHT -using System.Linq; -#endif - -namespace Ionic -{ - - /// - /// Enumerates the options for a logical conjunction. This enum is intended for use - /// internally by the FileSelector class. - /// - internal enum LogicalConjunction - { - NONE, - AND, - OR, - XOR, - } - - internal enum WhichTime - { - atime, - mtime, - ctime, - } - - - internal enum ComparisonOperator - { - [Description(">")] - GreaterThan, - [Description(">=")] - GreaterThanOrEqualTo, - [Description("<")] - LesserThan, - [Description("<=")] - LesserThanOrEqualTo, - [Description("=")] - EqualTo, - [Description("!=")] - NotEqualTo - } - - - internal abstract partial class SelectionCriterion - { - internal virtual bool Verbose - { - get;set; - } - internal abstract bool Evaluate(string filename); - - [System.Diagnostics.Conditional("SelectorTrace")] - protected static void CriterionTrace(string format, params object[] args) - { - //System.Console.WriteLine(" " + format, args); - } - } - - - internal partial class SizeCriterion : SelectionCriterion - { - internal ComparisonOperator Operator; - internal Int64 Size; - - public override String ToString() - { - StringBuilder sb = new StringBuilder(); - sb.Append("size ").Append(EnumUtil.GetDescription(Operator)).Append(" ").Append(Size.ToString()); - return sb.ToString(); - } - - internal override bool Evaluate(string filename) - { - System.IO.FileInfo fi = new System.IO.FileInfo(filename); - CriterionTrace("SizeCriterion::Evaluate('{0}' [{1}])", - filename, this.ToString()); - return _Evaluate(fi.Length); - } - - private bool _Evaluate(Int64 Length) - { - bool result = false; - switch (Operator) - { - case ComparisonOperator.GreaterThanOrEqualTo: - result = Length >= Size; - break; - case ComparisonOperator.GreaterThan: - result = Length > Size; - break; - case ComparisonOperator.LesserThanOrEqualTo: - result = Length <= Size; - break; - case ComparisonOperator.LesserThan: - result = Length < Size; - break; - case ComparisonOperator.EqualTo: - result = Length == Size; - break; - case ComparisonOperator.NotEqualTo: - result = Length != Size; - break; - default: - throw new ArgumentException("Operator"); - } - return result; - } - - } - - - - internal partial class TimeCriterion : SelectionCriterion - { - internal ComparisonOperator Operator; - internal WhichTime Which; - internal DateTime Time; - - public override String ToString() - { - StringBuilder sb = new StringBuilder(); - sb.Append(Which.ToString()).Append(" ").Append(EnumUtil.GetDescription(Operator)).Append(" ").Append(Time.ToString("yyyy-MM-dd-HH:mm:ss")); - return sb.ToString(); - } - - internal override bool Evaluate(string filename) - { - DateTime x; - switch (Which) - { - case WhichTime.atime: - x = System.IO.File.GetLastAccessTime(filename).ToUniversalTime(); - break; - case WhichTime.mtime: - x = System.IO.File.GetLastWriteTime(filename).ToUniversalTime(); - break; - case WhichTime.ctime: - x = System.IO.File.GetCreationTime(filename).ToUniversalTime(); - break; - default: - throw new ArgumentException("Operator"); - } - CriterionTrace("TimeCriterion({0},{1})= {2}", filename, Which.ToString(), x); - return _Evaluate(x); - } - - - private bool _Evaluate(DateTime x) - { - bool result = false; - switch (Operator) - { - case ComparisonOperator.GreaterThanOrEqualTo: - result = (x >= Time); - break; - case ComparisonOperator.GreaterThan: - result = (x > Time); - break; - case ComparisonOperator.LesserThanOrEqualTo: - result = (x <= Time); - break; - case ComparisonOperator.LesserThan: - result = (x < Time); - break; - case ComparisonOperator.EqualTo: - result = (x == Time); - break; - case ComparisonOperator.NotEqualTo: - result = (x != Time); - break; - default: - throw new ArgumentException("Operator"); - } - - CriterionTrace("TimeCriterion: {0}", result); - return result; - } - } - - - - internal partial class NameCriterion : SelectionCriterion - { - private Regex _re; - private String _regexString; - internal ComparisonOperator Operator; - private string _MatchingFileSpec; - internal virtual string MatchingFileSpec - { - set - { - // workitem 8245 - if (Directory.Exists(value)) - { - _MatchingFileSpec = ".\\" + value + "\\*.*"; - } - else - { - _MatchingFileSpec = value; - } - - _regexString = "^" + - Regex.Escape(_MatchingFileSpec) - .Replace(@"\\\*\.\*", @"\\([^\.]+|.*\.[^\\\.]*)") - .Replace(@"\.\*", @"\.[^\\\.]*") - .Replace(@"\*", @".*") - //.Replace(@"\*", @"[^\\\.]*") // ill-conceived - .Replace(@"\?", @"[^\\\.]") - + "$"; - - CriterionTrace("NameCriterion regexString({0})", _regexString); - - _re = new Regex(_regexString, RegexOptions.IgnoreCase); - } - } - - - public override String ToString() - { - StringBuilder sb = new StringBuilder(); - sb.Append("name ").Append(EnumUtil.GetDescription(Operator)) - .Append(" '") - .Append(_MatchingFileSpec) - .Append("'"); - return sb.ToString(); - } - - - internal override bool Evaluate(string filename) - { - CriterionTrace("NameCriterion::Evaluate('{0}' pattern[{1}])", - filename, _MatchingFileSpec); - return _Evaluate(filename); - } - - private bool _Evaluate(string fullpath) - { - CriterionTrace("NameCriterion::Evaluate({0})", fullpath); - // No slash in the pattern implicitly means recurse, which means compare to - // filename only, not full path. - String f = (_MatchingFileSpec.IndexOf('\\') == -1) - ? System.IO.Path.GetFileName(fullpath) - : fullpath; // compare to fullpath - - bool result = _re.IsMatch(f); - - if (Operator != ComparisonOperator.EqualTo) - result = !result; - return result; - } - } - - - internal partial class TypeCriterion : SelectionCriterion - { - private char ObjectType; // 'D' = Directory, 'F' = File - internal ComparisonOperator Operator; - internal string AttributeString - { - get - { - return ObjectType.ToString(); - } - set - { - if (value.Length != 1 || - (value[0]!='D' && value[0]!='F')) - throw new ArgumentException("Specify a single character: either D or F"); - ObjectType = value[0]; - } - } - - public override String ToString() - { - StringBuilder sb = new StringBuilder(); - sb.Append("type ").Append(EnumUtil.GetDescription(Operator)).Append(" ").Append(AttributeString); - return sb.ToString(); - } - - internal override bool Evaluate(string filename) - { - CriterionTrace("TypeCriterion::Evaluate({0})", filename); - - bool result = (ObjectType == 'D') - ? Directory.Exists(filename) - : File.Exists(filename); - - if (Operator != ComparisonOperator.EqualTo) - result = !result; - return result; - } - } - - -#if !SILVERLIGHT - internal partial class AttributesCriterion : SelectionCriterion - { - private FileAttributes _Attributes; - internal ComparisonOperator Operator; - internal string AttributeString - { - get - { - string result = ""; - if ((_Attributes & FileAttributes.Hidden) != 0) - result += "H"; - if ((_Attributes & FileAttributes.System) != 0) - result += "S"; - if ((_Attributes & FileAttributes.ReadOnly) != 0) - result += "R"; - if ((_Attributes & FileAttributes.Archive) != 0) - result += "A"; - if ((_Attributes & FileAttributes.ReparsePoint) != 0) - result += "L"; - if ((_Attributes & FileAttributes.NotContentIndexed) != 0) - result += "I"; - return result; - } - - set - { - _Attributes = FileAttributes.Normal; - foreach (char c in value.ToUpper()) - { - switch (c) - { - case 'H': - if ((_Attributes & FileAttributes.Hidden) != 0) - throw new ArgumentException(String.Format("Repeated flag. ({0})", c), "value"); - _Attributes |= FileAttributes.Hidden; - break; - - case 'R': - if ((_Attributes & FileAttributes.ReadOnly) != 0) - throw new ArgumentException(String.Format("Repeated flag. ({0})", c), "value"); - _Attributes |= FileAttributes.ReadOnly; - break; - - case 'S': - if ((_Attributes & FileAttributes.System) != 0) - throw new ArgumentException(String.Format("Repeated flag. ({0})", c), "value"); - _Attributes |= FileAttributes.System; - break; - - case 'A': - if ((_Attributes & FileAttributes.Archive) != 0) - throw new ArgumentException(String.Format("Repeated flag. ({0})", c), "value"); - _Attributes |= FileAttributes.Archive; - break; - - case 'I': - if ((_Attributes & FileAttributes.NotContentIndexed) != 0) - throw new ArgumentException(String.Format("Repeated flag. ({0})", c), "value"); - _Attributes |= FileAttributes.NotContentIndexed; - break; - - case 'L': - if ((_Attributes & FileAttributes.ReparsePoint) != 0) - throw new ArgumentException(String.Format("Repeated flag. ({0})", c), "value"); - _Attributes |= FileAttributes.ReparsePoint; - break; - - default: - throw new ArgumentException(value); - } - } - } - } - - - public override String ToString() - { - StringBuilder sb = new StringBuilder(); - sb.Append("attributes ").Append(EnumUtil.GetDescription(Operator)).Append(" ").Append(AttributeString); - return sb.ToString(); - } - - private bool _EvaluateOne(FileAttributes fileAttrs, FileAttributes criterionAttrs) - { - bool result = false; - if ((_Attributes & criterionAttrs) == criterionAttrs) - result = ((fileAttrs & criterionAttrs) == criterionAttrs); - else - result = true; - return result; - } - - - - internal override bool Evaluate(string filename) - { - // workitem 10191 - if (Directory.Exists(filename)) - { - // Directories don't have file attributes, so the result - // of an evaluation is always NO. This gets negated if - // the operator is NotEqualTo. - return (Operator != ComparisonOperator.EqualTo); - } -#if NETCF - FileAttributes fileAttrs = NetCfFile.GetAttributes(filename); -#else - FileAttributes fileAttrs = System.IO.File.GetAttributes(filename); -#endif - - return _Evaluate(fileAttrs); - } - - private bool _Evaluate(FileAttributes fileAttrs) - { - bool result = _EvaluateOne(fileAttrs, FileAttributes.Hidden); - if (result) - result = _EvaluateOne(fileAttrs, FileAttributes.System); - if (result) - result = _EvaluateOne(fileAttrs, FileAttributes.ReadOnly); - if (result) - result = _EvaluateOne(fileAttrs, FileAttributes.Archive); - if (result) - result = _EvaluateOne(fileAttrs, FileAttributes.NotContentIndexed); - if (result) - result = _EvaluateOne(fileAttrs, FileAttributes.ReparsePoint); - - if (Operator != ComparisonOperator.EqualTo) - result = !result; - - return result; - } - } -#endif - - - internal partial class CompoundCriterion : SelectionCriterion - { - internal LogicalConjunction Conjunction; - internal SelectionCriterion Left; - - private SelectionCriterion _Right; - internal SelectionCriterion Right - { - get { return _Right; } - set - { - _Right = value; - if (value == null) - Conjunction = LogicalConjunction.NONE; - else if (Conjunction == LogicalConjunction.NONE) - Conjunction = LogicalConjunction.AND; - } - } - - - internal override bool Evaluate(string filename) - { - bool result = Left.Evaluate(filename); - switch (Conjunction) - { - case LogicalConjunction.AND: - if (result) - result = Right.Evaluate(filename); - break; - case LogicalConjunction.OR: - if (!result) - result = Right.Evaluate(filename); - break; - case LogicalConjunction.XOR: - result ^= Right.Evaluate(filename); - break; - default: - throw new ArgumentException("Conjunction"); - } - return result; - } - - - public override String ToString() - { - StringBuilder sb = new StringBuilder(); - sb.Append("(") - .Append((Left != null) ? Left.ToString() : "null") - .Append(" ") - .Append(Conjunction.ToString()) - .Append(" ") - .Append((Right != null) ? Right.ToString() : "null") - .Append(")"); - return sb.ToString(); - } - } - - - - /// - /// FileSelector encapsulates logic that selects files from a source - a zip file - /// or the filesystem - based on a set of criteria. This class is used internally - /// by the DotNetZip library, in particular for the AddSelectedFiles() methods. - /// This class can also be used independently of the zip capability in DotNetZip. - /// - /// - /// - /// - /// - /// The FileSelector class is used internally by the ZipFile class for selecting - /// files for inclusion into the ZipFile, when the method, or one of - /// its overloads, is called. It's also used for the methods. Typically, an - /// application that creates or manipulates Zip archives will not directly - /// interact with the FileSelector class. - /// - /// - /// - /// Some applications may wish to use the FileSelector class directly, to - /// select files from disk volumes based on a set of criteria, without creating or - /// querying Zip archives. The file selection criteria include: a pattern to - /// match the filename; the last modified, created, or last accessed time of the - /// file; the size of the file; and the attributes of the file. - /// - /// - /// - /// Consult the documentation for - /// for more information on specifying the selection criteria. - /// - /// - /// - public partial class FileSelector - { - internal SelectionCriterion _Criterion; - -#if NOTUSED - /// - /// The default constructor. - /// - /// - /// Typically, applications won't use this constructor. Instead they'll - /// call the constructor that accepts a selectionCriteria string. If you - /// use this constructor, you'll want to set the SelectionCriteria - /// property on the instance before calling SelectFiles(). - /// - protected FileSelector() { } -#endif - /// - /// Constructor that allows the caller to specify file selection criteria. - /// - /// - /// - /// - /// This constructor allows the caller to specify a set of criteria for - /// selection of files. - /// - /// - /// - /// See for a description of - /// the syntax of the selectionCriteria string. - /// - /// - /// - /// By default the FileSelector will traverse NTFS Reparse Points. To - /// change this, use FileSelector(String, bool). - /// - /// - /// - /// The criteria for file selection. - public FileSelector(String selectionCriteria) - : this(selectionCriteria, true) - { - } - - /// - /// Constructor that allows the caller to specify file selection criteria. - /// - /// - /// - /// - /// This constructor allows the caller to specify a set of criteria for - /// selection of files. - /// - /// - /// - /// See for a description of - /// the syntax of the selectionCriteria string. - /// - /// - /// - /// The criteria for file selection. - /// - /// whether to traverse NTFS reparse points (junctions). - /// - public FileSelector(String selectionCriteria, bool traverseDirectoryReparsePoints) - { - if (!String.IsNullOrEmpty(selectionCriteria)) - _Criterion = _ParseCriterion(selectionCriteria); - TraverseReparsePoints = traverseDirectoryReparsePoints; - } - - - - /// - /// The string specifying which files to include when retrieving. - /// - /// - /// - /// - /// Specify the criteria in statements of 3 elements: a noun, an operator, - /// and a value. Consider the string "name != *.doc" . The noun is - /// "name". The operator is "!=", implying "Not Equal". The value is - /// "*.doc". That criterion, in English, says "all files with a name that - /// does not end in the .doc extension." - /// - /// - /// - /// Supported nouns include "name" (or "filename") for the filename; - /// "atime", "mtime", and "ctime" for last access time, last modfied time, - /// and created time of the file, respectively; "attributes" (or "attrs") - /// for the file attributes; "size" (or "length") for the file length - /// (uncompressed); and "type" for the type of object, either a file or a - /// directory. The "attributes", "type", and "name" nouns all support = - /// and != as operators. The "size", "atime", "mtime", and "ctime" nouns - /// support = and !=, and >, >=, <, <= as well. The times are - /// taken to be expressed in local time. - /// - /// - /// - /// Specify values for the file attributes as a string with one or more of - /// the characters H,R,S,A,I,L in any order, implying file attributes of - /// Hidden, ReadOnly, System, Archive, NotContextIndexed, and ReparsePoint - /// (symbolic link) respectively. - /// - /// - /// - /// To specify a time, use YYYY-MM-DD-HH:mm:ss or YYYY/MM/DD-HH:mm:ss as - /// the format. If you omit the HH:mm:ss portion, it is assumed to be - /// 00:00:00 (midnight). - /// - /// - /// - /// The value for a size criterion is expressed in integer quantities of - /// bytes, kilobytes (use k or kb after the number), megabytes (m or mb), - /// or gigabytes (g or gb). - /// - /// - /// - /// The value for a name is a pattern to match against the filename, - /// potentially including wildcards. The pattern follows CMD.exe glob - /// rules: * implies one or more of any character, while ? implies one - /// character. If the name pattern contains any slashes, it is matched to - /// the entire filename, including the path; otherwise, it is matched - /// against only the filename without the path. This means a pattern of - /// "*\*.*" matches all files one directory level deep, while a pattern of - /// "*.*" matches all files in all directories. - /// - /// - /// - /// To specify a name pattern that includes spaces, use single quotes - /// around the pattern. A pattern of "'* *.*'" will match all files that - /// have spaces in the filename. The full criteria string for that would - /// be "name = '* *.*'" . - /// - /// - /// - /// The value for a type criterion is either F (implying a file) or D - /// (implying a directory). - /// - /// - /// - /// Some examples: - /// - /// - /// - /// - /// criteria - /// Files retrieved - /// - /// - /// - /// name != *.xls - /// any file with an extension that is not .xls - /// - /// - /// - /// - /// name = *.mp3 - /// any file with a .mp3 extension. - /// - /// - /// - /// - /// *.mp3 - /// (same as above) any file with a .mp3 extension. - /// - /// - /// - /// - /// attributes = A - /// all files whose attributes include the Archive bit. - /// - /// - /// - /// - /// attributes != H - /// all files whose attributes do not include the Hidden bit. - /// - /// - /// - /// - /// mtime > 2009-01-01 - /// all files with a last modified time after January 1st, 2009. - /// - /// - /// - /// - /// ctime > 2009/01/01-03:00:00 - /// all files with a created time after 3am (local time), - /// on January 1st, 2009. - /// - /// - /// - /// - /// size > 2gb - /// all files whose uncompressed size is greater than 2gb. - /// - /// - /// - /// - /// type = D - /// all directories in the filesystem. - /// - /// - /// - /// - /// - /// You can combine criteria with the conjunctions AND, OR, and XOR. Using - /// a string like "name = *.txt AND size >= 100k" for the - /// selectionCriteria retrieves entries whose names end in .txt, and whose - /// uncompressed size is greater than or equal to 100 kilobytes. - /// - /// - /// - /// For more complex combinations of criteria, you can use parenthesis to - /// group clauses in the boolean logic. Absent parenthesis, the - /// precedence of the criterion atoms is determined by order of - /// appearance. Unlike the C# language, the AND conjunction does not take - /// precendence over the logical OR. This is important only in strings - /// that contain 3 or more criterion atoms. In other words, "name = *.txt - /// and size > 1000 or attributes = H" implies "((name = *.txt AND size - /// > 1000) OR attributes = H)" while "attributes = H OR name = *.txt - /// and size > 1000" evaluates to "((attributes = H OR name = *.txt) - /// AND size > 1000)". When in doubt, use parenthesis. - /// - /// - /// - /// Using time properties requires some extra care. If you want to - /// retrieve all entries that were last updated on 2009 February 14, - /// specify "mtime >= 2009-02-14 AND mtime < 2009-02-15". Read this - /// to say: all files updated after 12:00am on February 14th, until - /// 12:00am on February 15th. You can use the same bracketing approach to - /// specify any time period - a year, a month, a week, and so on. - /// - /// - /// - /// The syntax allows one special case: if you provide a string with no - /// spaces, it is treated as a pattern to match for the filename. - /// Therefore a string like "*.xls" will be equivalent to specifying "name - /// = *.xls". This "shorthand" notation does not work with compound - /// criteria. - /// - /// - /// - /// There is no logic in this class that insures that the inclusion - /// criteria are internally consistent. For example, it's possible to - /// specify criteria that says the file must have a size of less than 100 - /// bytes, as well as a size that is greater than 1000 bytes. Obviously - /// no file will ever satisfy such criteria, but this class does not check - /// for or detect such inconsistencies. - /// - /// - /// - /// - /// - /// Thrown in the setter if the value has an invalid syntax. - /// - public String SelectionCriteria - { - get - { - if (_Criterion == null) return null; - return _Criterion.ToString(); - } - set - { - if (value == null) _Criterion = null; - else if (value.Trim() == "") _Criterion = null; - else - _Criterion = _ParseCriterion(value); - } - } - - /// - /// Indicates whether searches will traverse NTFS reparse points, like Junctions. - /// - public bool TraverseReparsePoints - { - get; set; - } - - - private enum ParseState - { - Start, - OpenParen, - CriterionDone, - ConjunctionPending, - Whitespace, - } - - - private static class RegexAssertions - { - public static readonly String PrecededByOddNumberOfSingleQuotes = "(?<=(?:[^']*'[^']*')*'[^']*)"; - public static readonly String FollowedByOddNumberOfSingleQuotesAndLineEnd = "(?=[^']*'(?:[^']*'[^']*')*[^']*$)"; - - public static readonly String PrecededByEvenNumberOfSingleQuotes = "(?<=(?:[^']*'[^']*')*[^']*)"; - public static readonly String FollowedByEvenNumberOfSingleQuotesAndLineEnd = "(?=(?:[^']*'[^']*')*[^']*$)"; - } - - - private static string NormalizeCriteriaExpression(string source) - { - // The goal here is to normalize the criterion expression. At output, in - // the transformed criterion string, every significant syntactic element - // - a property element, grouping paren for the boolean logic, operator - // ( = < > != ), conjunction, or property value - will be separated from - // its neighbors by at least one space. Thus, - // - // before after - // ------------------------------------------------------------------- - // name=*.txt name = *.txt - // (size>100)AND(name=*.txt) ( size > 100 ) AND ( name = *.txt ) - // - // This is relatively straightforward using regular expression - // replacement. This method applies a distinct regex pattern and - // corresponding replacement string for each one of a number of cases: - // an open paren followed by a word; a word followed by a close-paren; a - // pair of open parens; a close paren followed by a word (which should - // then be followed by an open paren). And so on. These patterns and - // replacements are all stored in prPairs. By applying each of these - // regex replacements in turn, we get the transformed string. Easy. - // - // The resulting "normalized" criterion string, is then used as the - // subject that gets parsed, by splitting the string into tokens that - // are separated by spaces. Here, there's a twist. The spaces within - // single-quote delimiters do not delimit distinct tokens. So, this - // normalization method temporarily replaces those spaces with - // ASCII 6 (0x06), a control character which is not a legal - // character in a filename. The parsing logic that happens later will - // revert that change, restoring the original value of the filename - // specification. - // - // To illustrate, for a "before" string of [(size>100)AND(name='Name - // (with Parens).txt')] , the "after" string is [( size > 100 ) AND - // ( name = 'Name\u0006(with\u0006Parens).txt' )]. - // - - string[][] prPairs = - { - // A. opening double parens - insert a space between them - new string[] { @"([^']*)\(\(([^']+)", "$1( ($2" }, - - // B. closing double parens - insert a space between - new string[] { @"(.)\)\)", "$1) )" }, - - // C. single open paren with a following word - insert a space between - new string[] { @"\((\S)", "( $1" }, - - // D. single close paren with a preceding word - insert a space between the two - new string[] { @"(\S)\)", "$1 )" }, - - // E. close paren at line start?, insert a space before the close paren - // this seems like a degenerate case. I don't recall why it's here. - new string[] { @"^\)", " )" }, - - // F. a word (likely a conjunction) followed by an open paren - insert a space between - new string[] { @"(\S)\(", "$1 (" }, - - // G. single close paren followed by word - insert a paren after close paren - new string[] { @"\)(\S)", ") $1" }, - - // H. insert space between = and a following single quote - //new string[] { @"(=|!=)('[^']*')", "$1 $2" }, - new string[] { @"(=)('[^']*')", "$1 $2" }, - - // I. insert space between property names and the following operator - //new string[] { @"([^ ])([><(?:!=)=])", "$1 $2" }, - new string[] { @"([^ !><])(>|<|!=|=)", "$1 $2" }, - - // J. insert spaces between operators and the following values - //new string[] { @"([><(?:!=)=])([^ ])", "$1 $2" }, - new string[] { @"(>|<|!=|=)([^ =])", "$1 $2" }, - - // K. replace fwd slash with backslash - new string[] { @"/", "\\" }, - }; - - string interim = source; - - for (int i=0; i < prPairs.Length; i++) - { - //char caseIdx = (char)('A' + i); - string pattern = RegexAssertions.PrecededByEvenNumberOfSingleQuotes + - prPairs[i][0] + - RegexAssertions.FollowedByEvenNumberOfSingleQuotesAndLineEnd; - - interim = Regex.Replace(interim, pattern, prPairs[i][1]); - } - - // match a fwd slash, followed by an odd number of single quotes. - // This matches fwd slashes only inside a pair of single quote delimiters, - // eg, a filename. This must be done as well as the case above, to handle - // filenames specified inside quotes as well as filenames without quotes. - var regexPattern = @"/" + - RegexAssertions.FollowedByOddNumberOfSingleQuotesAndLineEnd; - // replace with backslash - interim = Regex.Replace(interim, regexPattern, "\\"); - - // match a space, followed by an odd number of single quotes. - // This matches spaces only inside a pair of single quote delimiters. - regexPattern = " " + - RegexAssertions.FollowedByOddNumberOfSingleQuotesAndLineEnd; - - // Replace all spaces that appear inside single quotes, with - // ascii 6. This allows a split on spaces to get tokens in - // the expression. The split will not split any filename or - // wildcard that appears within single quotes. After tokenizing, we - // need to replace ascii 6 with ascii 32 to revert the - // spaces within quotes. - return Regex.Replace(interim, regexPattern, "\u0006"); - } - - - private static SelectionCriterion _ParseCriterion(String s) - { - if (s == null) return null; - - // inject spaces after open paren and before close paren, etc - s = NormalizeCriteriaExpression(s); - - // no spaces in the criteria is shorthand for filename glob - if (s.IndexOf(" ") == -1) - s = "name = " + s; - - // split the expression into tokens - string[] tokens = s.Trim().Split(' ', '\t'); - - if (tokens.Length < 3) throw new ArgumentException(s); - - SelectionCriterion current = null; - - LogicalConjunction pendingConjunction = LogicalConjunction.NONE; - - ParseState state; - var stateStack = new System.Collections.Generic.Stack(); - var critStack = new System.Collections.Generic.Stack(); - stateStack.Push(ParseState.Start); - - for (int i = 0; i < tokens.Length; i++) - { - string tok1 = tokens[i].ToLower(); - switch (tok1) - { - case "and": - case "xor": - case "or": - state = stateStack.Peek(); - if (state != ParseState.CriterionDone) - throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); - - if (tokens.Length <= i + 3) - throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); - - pendingConjunction = (LogicalConjunction)Enum.Parse(typeof(LogicalConjunction), tokens[i].ToUpper(), true); - current = new CompoundCriterion { Left = current, Right = null, Conjunction = pendingConjunction }; - stateStack.Push(state); - stateStack.Push(ParseState.ConjunctionPending); - critStack.Push(current); - break; - - case "(": - state = stateStack.Peek(); - if (state != ParseState.Start && state != ParseState.ConjunctionPending && state != ParseState.OpenParen) - throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); - - if (tokens.Length <= i + 4) - throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); - - stateStack.Push(ParseState.OpenParen); - break; - - case ")": - state = stateStack.Pop(); - if (stateStack.Peek() != ParseState.OpenParen) - throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); - - stateStack.Pop(); - stateStack.Push(ParseState.CriterionDone); - break; - - case "atime": - case "ctime": - case "mtime": - if (tokens.Length <= i + 2) - throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); - - DateTime t; - try - { - t = DateTime.ParseExact(tokens[i + 2], "yyyy-MM-dd-HH:mm:ss", null); - } - catch (FormatException) - { - try - { - t = DateTime.ParseExact(tokens[i + 2], "yyyy/MM/dd-HH:mm:ss", null); - } - catch (FormatException) - { - try - { - t = DateTime.ParseExact(tokens[i + 2], "yyyy/MM/dd", null); - } - catch (FormatException) - { - try - { - t = DateTime.ParseExact(tokens[i + 2], "MM/dd/yyyy", null); - } - catch (FormatException) - { - t = DateTime.ParseExact(tokens[i + 2], "yyyy-MM-dd", null); - } - } - } - } - t= DateTime.SpecifyKind(t, DateTimeKind.Local).ToUniversalTime(); - current = new TimeCriterion - { - Which = (WhichTime)Enum.Parse(typeof(WhichTime), tokens[i], true), - Operator = (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), tokens[i + 1]), - Time = t - }; - i += 2; - stateStack.Push(ParseState.CriterionDone); - break; - - - case "length": - case "size": - if (tokens.Length <= i + 2) - throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); - - Int64 sz = 0; - string v = tokens[i + 2]; - if (v.ToUpper().EndsWith("K")) - sz = Int64.Parse(v.Substring(0, v.Length - 1)) * 1024; - else if (v.ToUpper().EndsWith("KB")) - sz = Int64.Parse(v.Substring(0, v.Length - 2)) * 1024; - else if (v.ToUpper().EndsWith("M")) - sz = Int64.Parse(v.Substring(0, v.Length - 1)) * 1024 * 1024; - else if (v.ToUpper().EndsWith("MB")) - sz = Int64.Parse(v.Substring(0, v.Length - 2)) * 1024 * 1024; - else if (v.ToUpper().EndsWith("G")) - sz = Int64.Parse(v.Substring(0, v.Length - 1)) * 1024 * 1024 * 1024; - else if (v.ToUpper().EndsWith("GB")) - sz = Int64.Parse(v.Substring(0, v.Length - 2)) * 1024 * 1024 * 1024; - else sz = Int64.Parse(tokens[i + 2]); - - current = new SizeCriterion - { - Size = sz, - Operator = (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), tokens[i + 1]) - }; - i += 2; - stateStack.Push(ParseState.CriterionDone); - break; - - case "filename": - case "name": - { - if (tokens.Length <= i + 2) - throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); - - ComparisonOperator c = - (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), tokens[i + 1]); - - if (c != ComparisonOperator.NotEqualTo && c != ComparisonOperator.EqualTo) - throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); - - string m = tokens[i + 2]; - - // handle single-quoted filespecs (used to include - // spaces in filename patterns) - if (m.StartsWith("'") && m.EndsWith("'")) - { - // trim off leading and trailing single quotes and - // revert the control characters to spaces. - m = m.Substring(1, m.Length - 2) - .Replace("\u0006", " "); - } - - // if (m.StartsWith("'")) - // m = m.Replace("\u0006", " "); - - current = new NameCriterion - { - MatchingFileSpec = m, - Operator = c - }; - i += 2; - stateStack.Push(ParseState.CriterionDone); - } - break; - -#if !SILVERLIGHT - case "attrs": - case "attributes": -#endif - case "type": - { - if (tokens.Length <= i + 2) - throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); - - ComparisonOperator c = - (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), tokens[i + 1]); - - if (c != ComparisonOperator.NotEqualTo && c != ComparisonOperator.EqualTo) - throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); - -#if SILVERLIGHT - current = (SelectionCriterion) new TypeCriterion - { - AttributeString = tokens[i + 2], - Operator = c - }; -#else - current = (tok1 == "type") - ? (SelectionCriterion) new TypeCriterion - { - AttributeString = tokens[i + 2], - Operator = c - } - : (SelectionCriterion) new AttributesCriterion - { - AttributeString = tokens[i + 2], - Operator = c - }; -#endif - i += 2; - stateStack.Push(ParseState.CriterionDone); - } - break; - - case "": - // NOP - stateStack.Push(ParseState.Whitespace); - break; - - default: - throw new ArgumentException("'" + tokens[i] + "'"); - } - - state = stateStack.Peek(); - if (state == ParseState.CriterionDone) - { - stateStack.Pop(); - if (stateStack.Peek() == ParseState.ConjunctionPending) - { - while (stateStack.Peek() == ParseState.ConjunctionPending) - { - var cc = critStack.Pop() as CompoundCriterion; - cc.Right = current; - current = cc; // mark the parent as current (walk up the tree) - stateStack.Pop(); // the conjunction is no longer pending - - state = stateStack.Pop(); - if (state != ParseState.CriterionDone) - throw new ArgumentException("??"); - } - } - else stateStack.Push(ParseState.CriterionDone); // not sure? - } - - if (state == ParseState.Whitespace) - stateStack.Pop(); - } - - return current; - } - - - /// - /// Returns a string representation of the FileSelector object. - /// - /// The string representation of the boolean logic statement of the file - /// selection criteria for this instance. - public override String ToString() - { - return "FileSelector("+_Criterion.ToString()+")"; - } - - - private bool Evaluate(string filename) - { - // dinoch - Thu, 11 Feb 2010 18:34 - SelectorTrace("Evaluate({0})", filename); - bool result = _Criterion.Evaluate(filename); - return result; - } - - [System.Diagnostics.Conditional("SelectorTrace")] - private void SelectorTrace(string format, params object[] args) - { - if (_Criterion != null && _Criterion.Verbose) - System.Console.WriteLine(format, args); - } - - /// - /// Returns the names of the files in the specified directory - /// that fit the selection criteria specified in the FileSelector. - /// - /// - /// - /// This is equivalent to calling - /// with recurseDirectories = false. - /// - /// - /// - /// The name of the directory over which to apply the FileSelector - /// criteria. - /// - /// - /// - /// A collection of strings containing fully-qualified pathnames of files - /// that match the criteria specified in the FileSelector instance. - /// - public System.Collections.Generic.ICollection SelectFiles(String directory) - { - return SelectFiles(directory, false); - } - - - /// - /// Returns the names of the files in the specified directory that fit the - /// selection criteria specified in the FileSelector, optionally recursing - /// through subdirectories. - /// - /// - /// - /// This method applies the file selection criteria contained in the - /// FileSelector to the files contained in the given directory, and - /// returns the names of files that conform to the criteria. - /// - /// - /// - /// The name of the directory over which to apply the FileSelector - /// criteria. - /// - /// - /// - /// Whether to recurse through subdirectories when applying the file - /// selection criteria. - /// - /// - /// - /// A collection of strings containing fully-qualified pathnames of files - /// that match the criteria specified in the FileSelector instance. - /// - public System.Collections.ObjectModel.ReadOnlyCollection - SelectFiles(String directory, - bool recurseDirectories) - { - if (_Criterion == null) - throw new ArgumentException("SelectionCriteria has not been set"); - - var list = new List(); - try - { - if (Directory.Exists(directory)) - { - String[] filenames = Directory.GetFiles(directory); - - // add the files: - foreach (String filename in filenames) - { - if (Evaluate(filename)) - list.Add(filename); - } - - if (recurseDirectories) - { - // add the subdirectories: - String[] dirnames = Directory.GetDirectories(directory); - foreach (String dir in dirnames) - { - if (this.TraverseReparsePoints -#if !SILVERLIGHT - || ((File.GetAttributes(dir) & FileAttributes.ReparsePoint) == 0) -#endif - ) - { - // workitem 10191 - if (Evaluate(dir)) list.Add(dir); - list.AddRange(this.SelectFiles(dir, recurseDirectories)); - } - } - } - } - } - // can get System.UnauthorizedAccessException here - catch (System.UnauthorizedAccessException) - { - } - catch (System.IO.IOException) - { - } - - return list.AsReadOnly(); - } - } - - - - /// - /// Summary description for EnumUtil. - /// - internal sealed class EnumUtil - { - private EnumUtil() { } - /// - /// Returns the value of the DescriptionAttribute if the specified Enum - /// value has one. If not, returns the ToString() representation of the - /// Enum value. - /// - /// The Enum to get the description for - /// - internal static string GetDescription(System.Enum value) - { - FieldInfo fi = value.GetType().GetField(value.ToString()); - var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false); - if (attributes.Length > 0) - return attributes[0].Description; - else - return value.ToString(); - } - - /// - /// Converts the string representation of the name or numeric value of one - /// or more enumerated constants to an equivalent enumerated object. - /// Note: use the DescriptionAttribute on enum values to enable this. - /// - /// The System.Type of the enumeration. - /// - /// A string containing the name or value to convert. - /// - /// - internal static object Parse(Type enumType, string stringRepresentation) - { - return Parse(enumType, stringRepresentation, false); - } - - -#if SILVERLIGHT - public static System.Enum[] GetEnumValues(Type type) - { - if (!type.IsEnum) - throw new ArgumentException("not an enum"); - - return ( - from field in type.GetFields(BindingFlags.Public | BindingFlags.Static) - where field.IsLiteral - select (System.Enum)field.GetValue(null) - ).ToArray(); - } - - public static string[] GetEnumStrings() - { - var type = typeof(T); - if (!type.IsEnum) - throw new ArgumentException("not an enum"); - - return ( - from field in type.GetFields(BindingFlags.Public | BindingFlags.Static) - where field.IsLiteral - select field.Name - ).ToArray(); - } -#endif - - /// - /// Converts the string representation of the name or numeric value of one - /// or more enumerated constants to an equivalent enumerated object. A - /// parameter specified whether the operation is case-sensitive. Note: - /// use the DescriptionAttribute on enum values to enable this. - /// - /// The System.Type of the enumeration. - /// - /// A string containing the name or value to convert. - /// - /// - /// Whether the operation is case-sensitive or not. - /// - internal static object Parse(Type enumType, string stringRepresentation, bool ignoreCase) - { - if (ignoreCase) - stringRepresentation = stringRepresentation.ToLower(); - -#if SILVERLIGHT - foreach (System.Enum enumVal in GetEnumValues(enumType)) -#else - foreach (System.Enum enumVal in System.Enum.GetValues(enumType)) -#endif - { - string description = GetDescription(enumVal); - if (ignoreCase) - description = description.ToLower(); - if (description == stringRepresentation) - return enumVal; - } - - return System.Enum.Parse(enumType, stringRepresentation, ignoreCase); - } - } - - -#if DEMO - public class DemonstrateFileSelector - { - private string _directory; - private bool _recurse; - private bool _traverse; - private bool _verbose; - private string _selectionCriteria; - private FileSelector f; - - public DemonstrateFileSelector() - { - this._directory = "."; - this._recurse = true; - } - - public DemonstrateFileSelector(string[] args) : this() - { - for (int i = 0; i < args.Length; i++) - { - switch(args[i]) - { - case"-?": - Usage(); - Environment.Exit(0); - break; - case "-d": - i++; - if (args.Length <= i) - throw new ArgumentException("-directory"); - this._directory = args[i]; - break; - case "-norecurse": - this._recurse = false; - break; - - case "-j-": - this._traverse = false; - break; - - case "-j+": - this._traverse = true; - break; - - case "-v": - this._verbose = true; - break; - - default: - if (this._selectionCriteria != null) - throw new ArgumentException(args[i]); - this._selectionCriteria = args[i]; - break; - } - - if (this._selectionCriteria != null) - this.f = new FileSelector(this._selectionCriteria); - } - } - - - public static void Main(string[] args) - { - try - { - Console.WriteLine(); - new DemonstrateFileSelector(args).Run(); - } - catch (Exception exc1) - { - Console.WriteLine("Exception: {0}", exc1.ToString()); - Usage(); - } - } - - - public void Run() - { - if (this.f == null) - this.f = new FileSelector("name = *.jpg AND (size > 1000 OR atime < 2009-02-14-01:00:00)"); - - this.f.TraverseReparsePoints = _traverse; - this.f.Verbose = this._verbose; - Console.WriteLine(); - Console.WriteLine(new String(':', 88)); - Console.WriteLine("Selecting files:\n" + this.f.ToString()); - var files = this.f.SelectFiles(this._directory, this._recurse); - if (files.Count == 0) - { - Console.WriteLine("no files."); - } - else - { - Console.WriteLine("files: {0}", files.Count); - foreach (string file in files) - { - Console.WriteLine(" " + file); - } - } - } - - public static void Usage() - { - Console.WriteLine("FileSelector: select files based on selection criteria.\n"); - Console.WriteLine("Usage:\n FileSelector [options]\n" + - "\n" + - " -d directory to select from (Default .)\n" + - " -norecurse don't recurse into subdirs\n" + - " -j- don't traverse junctions\n" + - " -v verbose output\n"); - } - } - -#endif - - - -} - - diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/OffsetStream.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/OffsetStream.cs deleted file mode 100644 index 525019ae..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/OffsetStream.cs +++ /dev/null @@ -1,114 +0,0 @@ -// OffsetStream.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2009 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: <2009-August-27 12:50:35> -// -// ------------------------------------------------------------------ -// -// This module defines logic for handling reading of zip archives embedded -// into larger streams. The initial position of the stream serves as -// the base offset for all future Seek() operations. -// -// ------------------------------------------------------------------ - - -using System; -using System.IO; - -namespace Ionic.Zip -{ - internal class OffsetStream : System.IO.Stream, System.IDisposable - { - private Int64 _originalPosition; - private Stream _innerStream; - - public OffsetStream(Stream s) - : base() - { - _originalPosition = s.Position; - _innerStream = s; - } - - public override int Read(byte[] buffer, int offset, int count) - { - return _innerStream.Read(buffer, offset, count); - } - - public override void Write(byte[] buffer, int offset, int count) - { - throw new NotImplementedException(); - } - - public override bool CanRead - { - get { return _innerStream.CanRead; } - } - - public override bool CanSeek - { - get { return _innerStream.CanSeek; } - } - - public override bool CanWrite - { - get { return false; } - } - - public override void Flush() - { - _innerStream.Flush(); - } - - public override long Length - { - get - { - return _innerStream.Length; - } - } - - public override long Position - { - get { return _innerStream.Position - _originalPosition; } - set { _innerStream.Position = _originalPosition + value; } - } - - - public override long Seek(long offset, System.IO.SeekOrigin origin) - { - return _innerStream.Seek(_originalPosition + offset, origin) - _originalPosition; - } - - - public override void SetLength(long value) - { - throw new NotImplementedException(); - } - - void IDisposable.Dispose() - { - Close(); - } - - public override void Close() - { - base.Close(); - } - - } - -} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/Shared.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/Shared.cs deleted file mode 100644 index cdc71618..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/Shared.cs +++ /dev/null @@ -1,901 +0,0 @@ -// Shared.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2006-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: <2011-August-02 19:41:01> -// -// ------------------------------------------------------------------ -// -// This module defines some shared utility classes and methods. -// -// Created: Tue, 27 Mar 2007 15:30 -// - -using System; -using System.IO; -using System.Security.Permissions; - -namespace Ionic.Zip -{ - /// - /// Collects general purpose utility methods. - /// - internal static class SharedUtilities - { - /// private null constructor - //private SharedUtilities() { } - - // workitem 8423 - public static Int64 GetFileLength(string fileName) - { - if (!File.Exists(fileName)) - throw new System.IO.FileNotFoundException(fileName); - - long fileLength = 0L; - FileShare fs = FileShare.ReadWrite; -#if !NETCF - // FileShare.Delete is not defined for the Compact Framework - fs |= FileShare.Delete; -#endif - using (var s = File.Open(fileName, FileMode.Open, FileAccess.Read, fs)) - { - fileLength = s.Length; - } - return fileLength; - } - - - [System.Diagnostics.Conditional("NETCF")] - public static void Workaround_Ladybug318918(Stream s) - { - // This is a workaround for this issue: - // https://connect.microsoft.com/VisualStudio/feedback/details/318918 - // It's required only on NETCF. - s.Flush(); - } - - -#if LEGACY - /// - /// Round the given DateTime value to an even second value. - /// - /// - /// - /// - /// Round up in the case of an odd second value. The rounding does not consider - /// fractional seconds. - /// - /// - /// This is useful because the Zip spec allows storage of time only to the nearest - /// even second. So if you want to compare the time of an entry in the archive with - /// it's actual time in the filesystem, you need to round the actual filesystem - /// time, or use a 2-second threshold for the comparison. - /// - /// - /// This is most nautrally an extension method for the DateTime class but this - /// library is built for .NET 2.0, not for .NET 3.5; This means extension methods - /// are a no-no. - /// - /// - /// The DateTime value to round - /// The ruonded DateTime value - public static DateTime RoundToEvenSecond(DateTime source) - { - // round to nearest second: - if ((source.Second % 2) == 1) - source += new TimeSpan(0, 0, 1); - - DateTime dtRounded = new DateTime(source.Year, source.Month, source.Day, source.Hour, source.Minute, source.Second); - //if (source.Millisecond >= 500) dtRounded = dtRounded.AddSeconds(1); - return dtRounded; - } -#endif - -#if YOU_LIKE_REDUNDANT_CODE - internal static string NormalizePath(string path) - { - // remove leading single dot slash - if (path.StartsWith(".\\")) path = path.Substring(2); - - // remove intervening dot-slash - path = path.Replace("\\.\\", "\\"); - - // remove double dot when preceded by a directory name - var re = new System.Text.RegularExpressions.Regex(@"^(.*\\)?([^\\\.]+\\\.\.\\)(.+)$"); - path = re.Replace(path, "$1$3"); - return path; - } -#endif - - private static System.Text.RegularExpressions.Regex doubleDotRegex1 = - new System.Text.RegularExpressions.Regex(@"^(.*/)?([^/\\.]+/\\.\\./)(.+)$"); - - private static string SimplifyFwdSlashPath(string path) - { - if (path.StartsWith("./")) path = path.Substring(2); - path = path.Replace("/./", "/"); - - // Replace foo/anything/../bar with foo/bar - path = doubleDotRegex1.Replace(path, "$1$3"); - return path; - } - - - /// - /// Utility routine for transforming path names from filesystem format (on Windows that means backslashes) to - /// a format suitable for use within zipfiles. This means trimming the volume letter and colon (if any) And - /// swapping backslashes for forward slashes. - /// - /// source path. - /// transformed path - public static string NormalizePathForUseInZipFile(string pathName) - { - // boundary case - if (String.IsNullOrEmpty(pathName)) return pathName; - - // trim volume if necessary - if ((pathName.Length >= 2) && ((pathName[1] == ':') && (pathName[2] == '\\'))) - pathName = pathName.Substring(3); - - // swap slashes - pathName = pathName.Replace('\\', '/'); - - // trim all leading slashes - while (pathName.StartsWith("/")) pathName = pathName.Substring(1); - - return SimplifyFwdSlashPath(pathName); - } - - - static System.Text.Encoding ibm437 = System.Text.Encoding.GetEncoding("IBM437"); - static System.Text.Encoding utf8 = System.Text.Encoding.GetEncoding("UTF-8"); - - internal static byte[] StringToByteArray(string value, System.Text.Encoding encoding) - { - byte[] a = encoding.GetBytes(value); - return a; - } - internal static byte[] StringToByteArray(string value) - { - return StringToByteArray(value, ibm437); - } - - //internal static byte[] Utf8StringToByteArray(string value) - //{ - // return StringToByteArray(value, utf8); - //} - - //internal static string StringFromBuffer(byte[] buf, int maxlength) - //{ - // return StringFromBuffer(buf, maxlength, ibm437); - //} - - internal static string Utf8StringFromBuffer(byte[] buf) - { - return StringFromBuffer(buf, utf8); - } - - internal static string StringFromBuffer(byte[] buf, System.Text.Encoding encoding) - { - // this form of the GetString() method is required for .NET CF compatibility - string s = encoding.GetString(buf, 0, buf.Length); - return s; - } - - - internal static int ReadSignature(System.IO.Stream s) - { - int x = 0; - try { x = _ReadFourBytes(s, "n/a"); } - catch (BadReadException) { } - return x; - } - - - internal static int ReadEntrySignature(System.IO.Stream s) - { - // handle the case of ill-formatted zip archives - includes a data descriptor - // when none is expected. - int x = 0; - try - { - x = _ReadFourBytes(s, "n/a"); - if (x == ZipConstants.ZipEntryDataDescriptorSignature) - { - // advance past data descriptor - 12 bytes if not zip64 - s.Seek(12, SeekOrigin.Current); - // workitem 10178 - Workaround_Ladybug318918(s); - x = _ReadFourBytes(s, "n/a"); - if (x != ZipConstants.ZipEntrySignature) - { - // Maybe zip64 was in use for the prior entry. - // Therefore, skip another 8 bytes. - s.Seek(8, SeekOrigin.Current); - // workitem 10178 - Workaround_Ladybug318918(s); - x = _ReadFourBytes(s, "n/a"); - if (x != ZipConstants.ZipEntrySignature) - { - // seek back to the first spot - s.Seek(-24, SeekOrigin.Current); - // workitem 10178 - Workaround_Ladybug318918(s); - x = _ReadFourBytes(s, "n/a"); - } - } - } - } - catch (BadReadException) { } - return x; - } - - - internal static int ReadInt(System.IO.Stream s) - { - return _ReadFourBytes(s, "Could not read block - no data! (position 0x{0:X8})"); - } - - private static int _ReadFourBytes(System.IO.Stream s, string message) - { - int n = 0; - byte[] block = new byte[4]; -#if NETCF - // workitem 9181 - // Reading here in NETCF sometimes reads "backwards". Seems to happen for - // larger files. Not sure why. Maybe an error in caching. If the data is: - // - // 00100210: 9efa 0f00 7072 6f6a 6563 742e 6963 7750 ....project.icwP - // 00100220: 4b05 0600 0000 0006 0006 0091 0100 008e K............... - // 00100230: 0010 0000 00 ..... - // - // ...and the stream Position is 10021F, then a Read of 4 bytes is returning - // 50776369, instead of 06054b50. This seems to happen the 2nd time Read() - // is called from that Position.. - // - // submitted to connect.microsoft.com - // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=318918#tabs - // - for (int i = 0; i < block.Length; i++) - { - n+= s.Read(block, i, 1); - } -#else - n = s.Read(block, 0, block.Length); -#endif - if (n != block.Length) throw new BadReadException(String.Format(message, s.Position)); - int data = unchecked((((block[3] * 256 + block[2]) * 256) + block[1]) * 256 + block[0]); - return data; - } - - - - /// - /// Finds a signature in the zip stream. This is useful for finding - /// the end of a zip entry, for example, or the beginning of the next ZipEntry. - /// - /// - /// - /// - /// Scans through 64k at a time. - /// - /// - /// - /// If the method fails to find the requested signature, the stream Position - /// after completion of this method is unchanged. If the method succeeds in - /// finding the requested signature, the stream position after completion is - /// direct AFTER the signature found in the stream. - /// - /// - /// - /// The stream to search - /// The 4-byte signature to find - /// The number of bytes read - internal static long FindSignature(System.IO.Stream stream, int SignatureToFind) - { - long startingPosition = stream.Position; - - int BATCH_SIZE = 65536; // 8192; - byte[] targetBytes = new byte[4]; - targetBytes[0] = (byte)(SignatureToFind >> 24); - targetBytes[1] = (byte)((SignatureToFind & 0x00FF0000) >> 16); - targetBytes[2] = (byte)((SignatureToFind & 0x0000FF00) >> 8); - targetBytes[3] = (byte)(SignatureToFind & 0x000000FF); - byte[] batch = new byte[BATCH_SIZE]; - int n = 0; - bool success = false; - do - { - n = stream.Read(batch, 0, batch.Length); - if (n != 0) - { - for (int i = 0; i < n; i++) - { - if (batch[i] == targetBytes[3]) - { - long curPosition = stream.Position; - stream.Seek(i - n, System.IO.SeekOrigin.Current); - // workitem 10178 - Workaround_Ladybug318918(stream); - - // workitem 7711 - int sig = ReadSignature(stream); - - success = (sig == SignatureToFind); - if (!success) - { - stream.Seek(curPosition, System.IO.SeekOrigin.Begin); - // workitem 10178 - Workaround_Ladybug318918(stream); - } - else - break; // out of for loop - } - } - } - else break; - if (success) break; - - } while (true); - - if (!success) - { - stream.Seek(startingPosition, System.IO.SeekOrigin.Begin); - // workitem 10178 - Workaround_Ladybug318918(stream); - return -1; // or throw? - } - - // subtract 4 for the signature. - long bytesRead = (stream.Position - startingPosition) - 4; - - return bytesRead; - } - - - // If I have a time in the .NET environment, and I want to use it for - // SetWastWriteTime() etc, then I need to adjust it for Win32. - internal static DateTime AdjustTime_Reverse(DateTime time) - { - if (time.Kind == DateTimeKind.Utc) return time; - DateTime adjusted = time; - if (DateTime.Now.IsDaylightSavingTime() && !time.IsDaylightSavingTime()) - adjusted = time - new System.TimeSpan(1, 0, 0); - - else if (!DateTime.Now.IsDaylightSavingTime() && time.IsDaylightSavingTime()) - adjusted = time + new System.TimeSpan(1, 0, 0); - - return adjusted; - } - -#if NECESSARY - // If I read a time from a file with GetLastWriteTime() (etc), I need - // to adjust it for display in the .NET environment. - internal static DateTime AdjustTime_Forward(DateTime time) - { - if (time.Kind == DateTimeKind.Utc) return time; - DateTime adjusted = time; - if (DateTime.Now.IsDaylightSavingTime() && !time.IsDaylightSavingTime()) - adjusted = time + new System.TimeSpan(1, 0, 0); - - else if (!DateTime.Now.IsDaylightSavingTime() && time.IsDaylightSavingTime()) - adjusted = time - new System.TimeSpan(1, 0, 0); - - return adjusted; - } -#endif - - - internal static DateTime PackedToDateTime(Int32 packedDateTime) - { - // workitem 7074 & workitem 7170 - if (packedDateTime == 0xFFFF || packedDateTime == 0) - return new System.DateTime(1995, 1, 1, 0, 0, 0, 0); // return a fixed date when none is supplied. - - Int16 packedTime = unchecked((Int16)(packedDateTime & 0x0000ffff)); - Int16 packedDate = unchecked((Int16)((packedDateTime & 0xffff0000) >> 16)); - - int year = 1980 + ((packedDate & 0xFE00) >> 9); - int month = (packedDate & 0x01E0) >> 5; - int day = packedDate & 0x001F; - - int hour = (packedTime & 0xF800) >> 11; - int minute = (packedTime & 0x07E0) >> 5; - //int second = packedTime & 0x001F; - int second = (packedTime & 0x001F) * 2; - - // validation and error checking. - // this is not foolproof but will catch most errors. - if (second >= 60) { minute++; second = 0; } - if (minute >= 60) { hour++; minute = 0; } - if (hour >= 24) { day++; hour = 0; } - - DateTime d = System.DateTime.Now; - bool success= false; - try - { - d = new System.DateTime(year, month, day, hour, minute, second, 0); - success= true; - } - catch (System.ArgumentOutOfRangeException) - { - if (year == 1980 && (month == 0 || day == 0)) - { - try - { - d = new System.DateTime(1980, 1, 1, hour, minute, second, 0); - success= true; - } - catch (System.ArgumentOutOfRangeException) - { - try - { - d = new System.DateTime(1980, 1, 1, 0, 0, 0, 0); - success= true; - } - catch (System.ArgumentOutOfRangeException) { } - - } - } - // workitem 8814 - // my god, I can't believe how many different ways applications - // can mess up a simple date format. - else - { - try - { - while (year < 1980) year++; - while (year > 2030) year--; - while (month < 1) month++; - while (month > 12) month--; - while (day < 1) day++; - while (day > 28) day--; - while (minute < 0) minute++; - while (minute > 59) minute--; - while (second < 0) second++; - while (second > 59) second--; - d = new System.DateTime(year, month, day, hour, minute, second, 0); - success= true; - } - catch (System.ArgumentOutOfRangeException) { } - } - } - if (!success) - { - string msg = String.Format("y({0}) m({1}) d({2}) h({3}) m({4}) s({5})", year, month, day, hour, minute, second); - throw new ZipException(String.Format("Bad date/time format in the zip file. ({0})", msg)); - - } - // workitem 6191 - //d = AdjustTime_Reverse(d); - d = DateTime.SpecifyKind(d, DateTimeKind.Local); - return d; - } - - - internal - static Int32 DateTimeToPacked(DateTime time) - { - // The time is passed in here only for purposes of writing LastModified to the - // zip archive. It should always be LocalTime, but we convert anyway. And, - // since the time is being written out, it needs to be adjusted. - - time = time.ToLocalTime(); - // workitem 7966 - //time = AdjustTime_Forward(time); - - // see http://www.vsft.com/hal/dostime.htm for the format - UInt16 packedDate = (UInt16)((time.Day & 0x0000001F) | ((time.Month << 5) & 0x000001E0) | (((time.Year - 1980) << 9) & 0x0000FE00)); - UInt16 packedTime = (UInt16)((time.Second / 2 & 0x0000001F) | ((time.Minute << 5) & 0x000007E0) | ((time.Hour << 11) & 0x0000F800)); - - Int32 result = (Int32)(((UInt32)(packedDate << 16)) | packedTime); - return result; - } - - - /// - /// Create a pseudo-random filename, suitable for use as a temporary - /// file, and open it. - /// - /// - /// - /// The System.IO.Path.GetRandomFileName() method is not available on - /// the Compact Framework, so this library provides its own substitute - /// on NETCF. - /// - /// - /// This method produces a filename of the form - /// DotNetZip-xxxxxxxx.tmp, where xxxxxxxx is replaced by randomly - /// chosen characters, and creates that file. - /// - /// - public static void CreateAndOpenUniqueTempFile(string dir, - out Stream fs, - out string filename) - { - // workitem 9763 - // http://dotnet.org.za/markn/archive/2006/04/15/51594.aspx - // try 3 times: - for (int i = 0; i < 3; i++) - { - try - { - filename = Path.Combine(dir, InternalGetTempFileName()); - fs = new FileStream(filename, FileMode.CreateNew); - return; - } - catch (IOException) - { - if (i == 2) throw; - } - } - throw new IOException(); - } - -#if NETCF || SILVERLIGHT - public static string InternalGetTempFileName() - { - return "DotNetZip-" + GenerateRandomStringImpl(8,0) + ".tmp"; - } - - internal static string GenerateRandomStringImpl(int length, int delta) - { - bool WantMixedCase = (delta == 0); - System.Random rnd = new System.Random(); - - string result = ""; - char[] a = new char[length]; - - for (int i = 0; i < length; i++) - { - // delta == 65 means uppercase - // delta == 97 means lowercase - if (WantMixedCase) - delta = (rnd.Next(2) == 0) ? 65 : 97; - a[i] = (char)(rnd.Next(26) + delta); - } - - result = new System.String(a); - return result; - } -#else - public static string InternalGetTempFileName() - { - return "DotNetZip-" + Path.GetRandomFileName().Substring(0, 8) + ".tmp"; - } - -#endif - - - /// - /// Workitem 7889: handle ERROR_LOCK_VIOLATION during read - /// - /// - /// This could be gracefully handled with an extension attribute, but - /// This assembly is built for .NET 2.0, so I cannot use them. - /// - internal static int ReadWithRetry(System.IO.Stream s, byte[] buffer, int offset, int count, string FileName) - { - int n = 0; - bool done = false; -#if !NETCF && !SILVERLIGHT - int retries = 0; -#endif - do - { - try - { - n = s.Read(buffer, offset, count); - done = true; - } -#if NETCF || SILVERLIGHT - catch (System.IO.IOException) - { - throw; - } -#else - catch (System.IO.IOException ioexc1) - { - // Check if we can call GetHRForException, - // which makes unmanaged code calls. - var p = new SecurityPermission(SecurityPermissionFlag.UnmanagedCode); - if (p.IsUnrestricted()) - { - uint hresult = _HRForException(ioexc1); - if (hresult != 0x80070021) // ERROR_LOCK_VIOLATION - throw new System.IO.IOException(String.Format("Cannot read file {0}", FileName), ioexc1); - retries++; - if (retries > 10) - throw new System.IO.IOException(String.Format("Cannot read file {0}, at offset 0x{1:X8} after 10 retries", FileName, offset), ioexc1); - - // max time waited on last retry = 250 + 10*550 = 5.75s - // aggregate time waited after 10 retries: 250 + 55*550 = 30.5s - System.Threading.Thread.Sleep(250 + retries * 550); - } - else - { - // The permission.Demand() failed. Therefore, we cannot call - // GetHRForException, and cannot do the subtle handling of - // ERROR_LOCK_VIOLATION. Just bail. - throw; - } - } -#endif - } - while (!done); - - return n; - } - - -#if !NETCF - // workitem 8009 - // - // This method must remain separate. - // - // Marshal.GetHRForException() is needed to do special exception handling for - // the read. But, that method requires UnmanagedCode permissions, and is marked - // with LinkDemand for UnmanagedCode. In an ASP.NET medium trust environment, - // where UnmanagedCode is restricted, will generate a SecurityException at the - // time of JIT of the method that calls a method that is marked with LinkDemand - // for UnmanagedCode. The SecurityException, if it is restricted, will occur - // when this method is JITed. - // - // The Marshal.GetHRForException() is factored out of ReadWithRetry in order to - // avoid the SecurityException at JIT compile time. Because _HRForException is - // called only when the UnmanagedCode is allowed. This means .NET never - // JIT-compiles this method when UnmanagedCode is disallowed, and thus never - // generates the JIT-compile time exception. - // -#endif - private static uint _HRForException(System.Exception ex1) - { - return unchecked((uint)System.Runtime.InteropServices.Marshal.GetHRForException(ex1)); - } - - } - - - - /// - /// A decorator stream. It wraps another stream, and performs bookkeeping - /// to keep track of the stream Position. - /// - /// - /// - /// In some cases, it is not possible to get the Position of a stream, let's - /// say, on a write-only output stream like ASP.NET's - /// Response.OutputStream, or on a different write-only stream - /// provided as the destination for the zip by the application. In this - /// case, programmers can use this counting stream to count the bytes read - /// or written. - /// - /// - /// Consider the scenario of an application that saves a self-extracting - /// archive (SFX), that uses a custom SFX stub. - /// - /// - /// Saving to a filesystem file, the application would open the - /// filesystem file (getting a FileStream), save the custom sfx stub - /// into it, and then call ZipFile.Save(), specifying the same - /// FileStream. ZipFile.Save() does the right thing for the zipentry - /// offsets, by inquiring the Position of the FileStream before writing - /// any data, and then adding that initial offset into any ZipEntry - /// offsets in the zip directory. Everything works fine. - /// - /// - /// Now suppose the application is an ASPNET application and it saves - /// directly to Response.OutputStream. It's not possible for DotNetZip to - /// inquire the Position, so the offsets for the SFX will be wrong. - /// - /// - /// The workaround is for the application to use this class to wrap - /// HttpResponse.OutputStream, then write the SFX stub and the ZipFile - /// into that wrapper stream. Because ZipFile.Save() can inquire the - /// Position, it will then do the right thing with the offsets. - /// - /// - public class CountingStream : System.IO.Stream - { - // workitem 12374: this class is now public - private System.IO.Stream _s; - private Int64 _bytesWritten; - private Int64 _bytesRead; - private Int64 _initialOffset; - - /// - /// The constructor. - /// - /// The underlying stream - public CountingStream(System.IO.Stream stream) - : base() - { - _s = stream; - try - { - _initialOffset = _s.Position; - } - catch - { - _initialOffset = 0L; - } - } - - /// - /// Gets the wrapped stream. - /// - public Stream WrappedStream - { - get - { - return _s; - } - } - - /// - /// The count of bytes written out to the stream. - /// - public Int64 BytesWritten - { - get { return _bytesWritten; } - } - - /// - /// the count of bytes that have been read from the stream. - /// - public Int64 BytesRead - { - get { return _bytesRead; } - } - - /// - /// Adjust the byte count on the stream. - /// - /// - /// - /// the number of bytes to subtract from the count. - /// - /// - /// - /// - /// Subtract delta from the count of bytes written to the stream. - /// This is necessary when seeking back, and writing additional data, - /// as happens in some cases when saving Zip files. - /// - /// - public void Adjust(Int64 delta) - { - _bytesWritten -= delta; - if (_bytesWritten < 0) - throw new InvalidOperationException(); - if (_s as CountingStream != null) - ((CountingStream)_s).Adjust(delta); - } - - /// - /// The read method. - /// - /// The buffer to hold the data read from the stream. - /// the offset within the buffer to copy the first byte read. - /// the number of bytes to read. - /// the number of bytes read, after decryption and decompression. - public override int Read(byte[] buffer, int offset, int count) - { - int n = _s.Read(buffer, offset, count); - _bytesRead += n; - return n; - } - - /// - /// Write data into the stream. - /// - /// The buffer holding data to write to the stream. - /// the offset within that data array to find the first byte to write. - /// the number of bytes to write. - public override void Write(byte[] buffer, int offset, int count) - { - if (count == 0) return; - _s.Write(buffer, offset, count); - _bytesWritten += count; - } - - /// - /// Whether the stream can be read. - /// - public override bool CanRead - { - get { return _s.CanRead; } - } - - /// - /// Whether it is possible to call Seek() on the stream. - /// - public override bool CanSeek - { - get { return _s.CanSeek; } - } - - /// - /// Whether it is possible to call Write() on the stream. - /// - public override bool CanWrite - { - get { return _s.CanWrite; } - } - - /// - /// Flushes the underlying stream. - /// - public override void Flush() - { - _s.Flush(); - } - - /// - /// The length of the underlying stream. - /// - public override long Length - { - get { return _s.Length; } // bytesWritten?? - } - - /// - /// Returns the sum of number of bytes written, plus the initial - /// offset before writing. - /// - public long ComputedPosition - { - get { return _initialOffset + _bytesWritten; } - } - - - /// - /// The Position of the stream. - /// - public override long Position - { - get { return _s.Position; } - set - { - _s.Seek(value, System.IO.SeekOrigin.Begin); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(_s); - } - } - - /// - /// Seek in the stream. - /// - /// the offset point to seek to - /// the reference point from which to seek - /// The new position - public override long Seek(long offset, System.IO.SeekOrigin origin) - { - return _s.Seek(offset, origin); - } - - /// - /// Set the length of the underlying stream. Be careful with this! - /// - /// - /// the length to set on the underlying stream. - public override void SetLength(long value) - { - _s.SetLength(value); - } - } - - -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/WinZipAes.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/WinZipAes.cs deleted file mode 100644 index a316b91b..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/WinZipAes.cs +++ /dev/null @@ -1,941 +0,0 @@ -//#define Trace - -// WinZipAes.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-12 13:42:06> -// -// ------------------------------------------------------------------ -// -// This module defines the classes for dealing with WinZip's AES encryption, -// according to the specifications for the format available on WinZip's website. -// -// Created: January 2009 -// -// ------------------------------------------------------------------ - -using System; -using System.IO; -using System.Collections.Generic; -using System.Security.Cryptography; - -#if AESCRYPTO -namespace Ionic.Zip -{ - /// - /// This is a helper class supporting WinZip AES encryption. - /// This class is intended for use only by the DotNetZip library. - /// - /// - /// - /// Most uses of the DotNetZip library will not involve direct calls into - /// the WinZipAesCrypto class. Instead, the WinZipAesCrypto class is - /// instantiated and used by the ZipEntry() class when WinZip AES - /// encryption or decryption on an entry is employed. - /// - internal class WinZipAesCrypto - { - internal byte[] _Salt; - internal byte[] _providedPv; - internal byte[] _generatedPv; - internal int _KeyStrengthInBits; - private byte[] _MacInitializationVector; - private byte[] _StoredMac; - private byte[] _keyBytes; - private Int16 PasswordVerificationStored; - private Int16 PasswordVerificationGenerated; - private int Rfc2898KeygenIterations = 1000; - private string _Password; - private bool _cryptoGenerated ; - - private WinZipAesCrypto(string password, int KeyStrengthInBits) - { - _Password = password; - _KeyStrengthInBits = KeyStrengthInBits; - } - - public static WinZipAesCrypto Generate(string password, int KeyStrengthInBits) - { - WinZipAesCrypto c = new WinZipAesCrypto(password, KeyStrengthInBits); - - int saltSizeInBytes = c._KeyStrengthInBytes / 2; - c._Salt = new byte[saltSizeInBytes]; - Random rnd = new Random(); - rnd.NextBytes(c._Salt); - return c; - } - - - - public static WinZipAesCrypto ReadFromStream(string password, int KeyStrengthInBits, Stream s) - { - // from http://www.winzip.com/aes_info.htm - // - // Size(bytes) Content - // ----------------------------------- - // Variable Salt value - // 2 Password verification value - // Variable Encrypted file data - // 10 Authentication code - // - // ZipEntry.CompressedSize represents the size of all of those elements. - - // salt size varies with key length: - // 128 bit key => 8 bytes salt - // 192 bits => 12 bytes salt - // 256 bits => 16 bytes salt - - WinZipAesCrypto c = new WinZipAesCrypto(password, KeyStrengthInBits); - - int saltSizeInBytes = c._KeyStrengthInBytes / 2; - c._Salt = new byte[saltSizeInBytes]; - c._providedPv = new byte[2]; - - s.Read(c._Salt, 0, c._Salt.Length); - s.Read(c._providedPv, 0, c._providedPv.Length); - - c.PasswordVerificationStored = (Int16)(c._providedPv[0] + c._providedPv[1] * 256); - if (password != null) - { - c.PasswordVerificationGenerated = (Int16)(c.GeneratedPV[0] + c.GeneratedPV[1] * 256); - if (c.PasswordVerificationGenerated != c.PasswordVerificationStored) - throw new BadPasswordException("bad password"); - } - - return c; - } - - public byte[] GeneratedPV - { - get - { - if (!_cryptoGenerated) _GenerateCryptoBytes(); - return _generatedPv; - } - } - - - public byte[] Salt - { - get - { - return _Salt; - } - } - - - private int _KeyStrengthInBytes - { - get - { - return _KeyStrengthInBits / 8; - - } - } - - public int SizeOfEncryptionMetadata - { - get - { - // 10 bytes after, (n-10) before the compressed data - return _KeyStrengthInBytes / 2 + 10 + 2; - } - } - - public string Password - { - set - { - _Password = value; - if (_Password != null) - { - PasswordVerificationGenerated = (Int16)(GeneratedPV[0] + GeneratedPV[1] * 256); - if (PasswordVerificationGenerated != PasswordVerificationStored) - throw new Ionic.Zip.BadPasswordException(); - } - } - private get - { - return _Password; - } - } - - - private void _GenerateCryptoBytes() - { - //Console.WriteLine(" provided password: '{0}'", _Password); - - System.Security.Cryptography.Rfc2898DeriveBytes rfc2898 = - new System.Security.Cryptography.Rfc2898DeriveBytes(_Password, Salt, Rfc2898KeygenIterations); - - _keyBytes = rfc2898.GetBytes(_KeyStrengthInBytes); // 16 or 24 or 32 ??? - _MacInitializationVector = rfc2898.GetBytes(_KeyStrengthInBytes); - _generatedPv = rfc2898.GetBytes(2); - - _cryptoGenerated = true; - } - - - public byte[] KeyBytes - { - get - { - if (!_cryptoGenerated) _GenerateCryptoBytes(); - return _keyBytes; - } - } - - - public byte[] MacIv - { - get - { - if (!_cryptoGenerated) _GenerateCryptoBytes(); - return _MacInitializationVector; - } - } - - public byte[] CalculatedMac; - - - public void ReadAndVerifyMac(System.IO.Stream s) - { - bool invalid = false; - - // read integrityCheckVector. - // caller must ensure that the file pointer is in the right spot! - _StoredMac = new byte[10]; // aka "authentication code" - s.Read(_StoredMac, 0, _StoredMac.Length); - - if (_StoredMac.Length != CalculatedMac.Length) - invalid = true; - - if (!invalid) - { - for (int i = 0; i < _StoredMac.Length; i++) - { - if (_StoredMac[i] != CalculatedMac[i]) - invalid = true; - } - } - - if (invalid) - throw new Ionic.Zip.BadStateException("The MAC does not match."); - } - - } - - - #region DONT_COMPILE_BUT_KEEP_FOR_POTENTIAL_FUTURE_USE -#if NO - internal class Util - { - private static void _Format(System.Text.StringBuilder sb1, - byte[] b, - int offset, - int length) - { - - System.Text.StringBuilder sb2 = new System.Text.StringBuilder(); - sb1.Append("0000 "); - int i; - for (i = 0; i < length; i++) - { - int x = offset+i; - if (i != 0 && i % 16 == 0) - { - sb1.Append(" ") - .Append(sb2) - .Append("\n") - .Append(String.Format("{0:X4} ", i)); - sb2.Remove(0,sb2.Length); - } - sb1.Append(System.String.Format("{0:X2} ", b[x])); - if (b[x] >=32 && b[x] <= 126) - sb2.Append((char)b[x]); - else - sb2.Append("."); - } - if (sb2.Length > 0) - { - sb1.Append(new String(' ', ((16 - i%16) * 3) + 4)) - .Append(sb2); - } - } - - - - internal static string FormatByteArray(byte[] b, int limit) - { - System.Text.StringBuilder sb1 = new System.Text.StringBuilder(); - - if ((limit * 2 > b.Length) || limit == 0) - { - _Format(sb1, b, 0, b.Length); - } - else - { - // first N bytes of the buffer - _Format(sb1, b, 0, limit); - - if (b.Length > limit * 2) - sb1.Append(String.Format("\n ...({0} other bytes here)....\n", b.Length - limit * 2)); - - // last N bytes of the buffer - _Format(sb1, b, b.Length - limit, limit); - } - - return sb1.ToString(); - } - - - internal static string FormatByteArray(byte[] b) - { - return FormatByteArray(b, 0); - } - } - -#endif - #endregion - - - - - /// - /// A stream that encrypts as it writes, or decrypts as it reads. The - /// Crypto is AES in CTR (counter) mode, which is compatible with the AES - /// encryption employed by WinZip 12.0. - /// - /// - /// - /// The AES/CTR encryption protocol used by WinZip works like this: - /// - /// - start with a counter, initialized to zero. - /// - /// - to encrypt, take the data by 16-byte blocks. For each block: - /// - apply the transform to the counter - /// - increement the counter - /// - XOR the result of the transform with the plaintext to - /// get the ciphertext. - /// - compute the mac on the encrypted bytes - /// - when finished with all blocks, store the computed MAC. - /// - /// - to decrypt, take the data by 16-byte blocks. For each block: - /// - compute the mac on the encrypted bytes, - /// - apply the transform to the counter - /// - increement the counter - /// - XOR the result of the transform with the ciphertext to - /// get the plaintext. - /// - when finished with all blocks, compare the computed MAC against - /// the stored MAC - /// - /// - /// - // - internal class WinZipAesCipherStream : Stream - { - private WinZipAesCrypto _params; - private System.IO.Stream _s; - private CryptoMode _mode; - private int _nonce; - private bool _finalBlock; - - internal HMACSHA1 _mac; - - // Use RijndaelManaged from .NET 2.0. - // AesManaged came in .NET 3.5, but we want to limit - // dependency to .NET 2.0. AES is just a restricted form - // of Rijndael (fixed block size of 128, some crypto modes not supported). - - internal RijndaelManaged _aesCipher; - internal ICryptoTransform _xform; - - private const int BLOCK_SIZE_IN_BYTES = 16; - - private byte[] counter = new byte[BLOCK_SIZE_IN_BYTES]; - private byte[] counterOut = new byte[BLOCK_SIZE_IN_BYTES]; - - // I've had a problem when wrapping a WinZipAesCipherStream inside - // a DeflateStream. Calling Read() on the DeflateStream results in - // a Read() on the WinZipAesCipherStream, but the buffer is larger - // than the total size of the encrypted data, and larger than the - // initial Read() on the DeflateStream! When the encrypted - // bytestream is embedded within a larger stream (As in a zip - // archive), the Read() doesn't fail with EOF. This causes bad - // data to be returned, and it messes up the MAC. - - // This field is used to provide a hard-stop to the size of - // data that can be read from the stream. In Read(), if the buffer or - // read request goes beyond the stop, we truncate it. - - private long _length; - private long _totalBytesXferred; - private byte[] _PendingWriteBlock; - private int _pendingCount; - private byte[] _iobuf; - - /// - /// The constructor. - /// - /// The underlying stream - /// To either encrypt or decrypt. - /// The pre-initialized WinZipAesCrypto object. - /// The maximum number of bytes to read from the stream. - internal WinZipAesCipherStream(System.IO.Stream s, WinZipAesCrypto cryptoParams, long length, CryptoMode mode) - : this(s, cryptoParams, mode) - { - // don't read beyond this limit! - _length = length; - //Console.WriteLine("max length of AES stream: {0}", _length); - } - - -#if WANT_TRACE - Stream untransformed; - String traceFileUntransformed; - Stream transformed; - String traceFileTransformed; -#endif - - - internal WinZipAesCipherStream(System.IO.Stream s, WinZipAesCrypto cryptoParams, CryptoMode mode) - : base() - { - TraceOutput("-------------------------------------------------------"); - TraceOutput("Create {0:X8}", this.GetHashCode()); - - _params = cryptoParams; - _s = s; - _mode = mode; - _nonce = 1; - - if (_params == null) - throw new BadPasswordException("Supply a password to use AES encryption."); - - int keySizeInBits = _params.KeyBytes.Length * 8; - if (keySizeInBits != 256 && keySizeInBits != 128 && keySizeInBits != 192) - throw new ArgumentOutOfRangeException("keysize", - "size of key must be 128, 192, or 256"); - - _mac = new HMACSHA1(_params.MacIv); - - _aesCipher = new System.Security.Cryptography.RijndaelManaged(); - _aesCipher.BlockSize = 128; - _aesCipher.KeySize = keySizeInBits; // 128, 192, 256 - _aesCipher.Mode = CipherMode.ECB; - _aesCipher.Padding = PaddingMode.None; - - byte[] iv = new byte[BLOCK_SIZE_IN_BYTES]; // all zeroes - - // Create an ENCRYPTOR, regardless whether doing decryption or encryption. - // It is reflexive. - _xform = _aesCipher.CreateEncryptor(_params.KeyBytes, iv); - - if (_mode == CryptoMode.Encrypt) - { - _iobuf = new byte[2048]; - _PendingWriteBlock = new byte[BLOCK_SIZE_IN_BYTES]; - } - - -#if WANT_TRACE - traceFileUntransformed = "unpack\\WinZipAesCipherStream.trace.untransformed.out"; - traceFileTransformed = "unpack\\WinZipAesCipherStream.trace.transformed.out"; - - untransformed = System.IO.File.Create(traceFileUntransformed); - transformed = System.IO.File.Create(traceFileTransformed); -#endif - } - - private void XorInPlace(byte[] buffer, int offset, int count) - { - for (int i = 0; i < count; i++) - { - buffer[offset + i] = (byte)(counterOut[i] ^ buffer[offset + i]); - } - } - - private void WriteTransformOneBlock(byte[] buffer, int offset) - { - System.Array.Copy(BitConverter.GetBytes(_nonce++), 0, counter, 0, 4); - _xform.TransformBlock(counter, - 0, - BLOCK_SIZE_IN_BYTES, - counterOut, - 0); - XorInPlace(buffer, offset, BLOCK_SIZE_IN_BYTES); - _mac.TransformBlock(buffer, offset, BLOCK_SIZE_IN_BYTES, null, 0); - } - - - private void WriteTransformBlocks(byte[] buffer, int offset, int count) - { - int posn = offset; - int last = count + offset; - - while (posn < buffer.Length && posn < last) - { - WriteTransformOneBlock (buffer, posn); - posn += BLOCK_SIZE_IN_BYTES; - } - } - - - private void WriteTransformFinalBlock() - { - if (_pendingCount == 0) - throw new InvalidOperationException("No bytes available."); - - if (_finalBlock) - throw new InvalidOperationException("The final block has already been transformed."); - - System.Array.Copy(BitConverter.GetBytes(_nonce++), 0, counter, 0, 4); - counterOut = _xform.TransformFinalBlock(counter, - 0, - BLOCK_SIZE_IN_BYTES); - XorInPlace(_PendingWriteBlock, 0, _pendingCount); - _mac.TransformFinalBlock(_PendingWriteBlock, 0, _pendingCount); - _finalBlock = true; - } - - - - - - private int ReadTransformOneBlock(byte[] buffer, int offset, int last) - { - if (_finalBlock) - throw new NotSupportedException(); - - int bytesRemaining = last - offset; - int bytesToRead = (bytesRemaining > BLOCK_SIZE_IN_BYTES) - ? BLOCK_SIZE_IN_BYTES - : bytesRemaining; - - // update the counter - System.Array.Copy(BitConverter.GetBytes(_nonce++), 0, counter, 0, 4); - - // Determine if this is the final block - if ((bytesToRead == bytesRemaining) && - (_length > 0) && - (_totalBytesXferred + last == _length)) - { - _mac.TransformFinalBlock(buffer, offset, bytesToRead); - counterOut = _xform.TransformFinalBlock(counter, - 0, - BLOCK_SIZE_IN_BYTES); - _finalBlock = true; - } - else - { - _mac.TransformBlock(buffer, offset, bytesToRead, null, 0); - _xform.TransformBlock(counter, - 0, // offset - BLOCK_SIZE_IN_BYTES, - counterOut, - 0); // offset - } - - XorInPlace(buffer, offset, bytesToRead); - return bytesToRead; - } - - - - private void ReadTransformBlocks(byte[] buffer, int offset, int count) - { - int posn = offset; - int last = count + offset; - - while (posn < buffer.Length && posn < last ) - { - int n = ReadTransformOneBlock (buffer, posn, last); - posn += n; - } - } - - - - public override int Read(byte[] buffer, int offset, int count) - { - if (_mode == CryptoMode.Encrypt) - throw new NotSupportedException(); - - if (buffer == null) - throw new ArgumentNullException("buffer"); - - if (offset < 0) - throw new ArgumentOutOfRangeException("offset", - "Must not be less than zero."); - if (count < 0) - throw new ArgumentOutOfRangeException("count", - "Must not be less than zero."); - - if (buffer.Length < offset + count) - throw new ArgumentException("The buffer is too small"); - - // When I wrap a WinZipAesStream in a DeflateStream, the - // DeflateStream asks its captive to read 4k blocks, even if the - // encrypted bytestream is smaller than that. This is a way to - // limit the number of bytes read. - - int bytesToRead = count; - - if (_totalBytesXferred >= _length) - { - return 0; // EOF - } - - long bytesRemaining = _length - _totalBytesXferred; - if (bytesRemaining < count) bytesToRead = (int)bytesRemaining; - - int n = _s.Read(buffer, offset, bytesToRead); - - -#if WANT_TRACE - untransformed.Write(buffer, offset, bytesToRead); -#endif - - ReadTransformBlocks(buffer, offset, bytesToRead); - -#if WANT_TRACE - transformed.Write(buffer, offset, bytesToRead); -#endif - _totalBytesXferred += n; - return n; - } - - - - /// - /// Returns the final HMAC-SHA1-80 for the data that was encrypted. - /// - public byte[] FinalAuthentication - { - get - { - if (!_finalBlock) - { - // special-case zero-byte files - if ( _totalBytesXferred != 0) - throw new BadStateException("The final hash has not been computed."); - - // Must call ComputeHash on an empty byte array when no data - // has run through the MAC. - - byte[] b = { }; - _mac.ComputeHash(b); - // fall through - } - byte[] macBytes10 = new byte[10]; - System.Array.Copy(_mac.Hash, 0, macBytes10, 0, 10); - return macBytes10; - } - } - - - public override void Write(byte[] buffer, int offset, int count) - { - if (_finalBlock) - throw new InvalidOperationException("The final block has already been transformed."); - - if (_mode == CryptoMode.Decrypt) - throw new NotSupportedException(); - - if (buffer == null) - throw new ArgumentNullException("buffer"); - - if (offset < 0) - throw new ArgumentOutOfRangeException("offset", - "Must not be less than zero."); - if (count < 0) - throw new ArgumentOutOfRangeException("count", - "Must not be less than zero."); - if (buffer.Length < offset + count) - throw new ArgumentException("The offset and count are too large"); - - if (count == 0) - return; - - TraceOutput("Write off({0}) count({1})", offset, count); - -#if WANT_TRACE - untransformed.Write(buffer, offset, count); -#endif - - // For proper AES encryption, an AES encryptor application calls - // TransformBlock repeatedly for all 16-byte blocks except the - // last. For the last block, it then calls TransformFinalBlock(). - // - // This class is a stream that encrypts via Write(). But, it's not - // possible to recognize which are the "last" bytes from within the call - // to Write(). The caller can call Write() several times in succession, - // with varying buffers. This class only "knows" that the last bytes - // have been written when the app calls Close(). - // - // Therefore, this class buffers writes: After completion every Write(), - // a 16-byte "pending" block (_PendingWriteBlock) must hold between 1 - // and 16 bytes, which will be used in TransformFinalBlock if the app - // calls Close() immediately thereafter. Also, every write must - // transform any pending bytes, before transforming the data passed in - // to the current call. - // - // In operation, after the first call to Write() and before the call to - // Close(), one full or partial block of bytes is always available, - // pending. At time of Close(), this class calls - // WriteTransformFinalBlock() to flush the pending bytes. - // - // This approach works whether the caller writes in odd-sized batches, - // for example 5000 bytes, or in batches that are neat multiples of the - // blocksize (16). - // - // Logicaly, what we do is this: - // - // 1. if there are fewer than 16 bytes (pending + current), then - // just copy them into th pending buffer and return. - // - // 2. there are more than 16 bytes to write. So, take the leading slice - // of bytes from the current buffer, enough to fill the pending - // buffer. Transform the pending block, and write it out. - // - // 3. Take the trailing slice of bytes (a full block or a partial block), - // and copy it to the pending block for next time. - // - // 4. transform and write all the other blocks, the middle slice. - // - - // There are 16 or fewer bytes, so just buffer the bytes. - if (count + _pendingCount <= BLOCK_SIZE_IN_BYTES) - { - Buffer.BlockCopy(buffer, - offset, - _PendingWriteBlock, - _pendingCount, - count); - _pendingCount += count; - - // At this point, _PendingWriteBlock contains up to - // BLOCK_SIZE_IN_BYTES bytes, and _pendingCount ranges from 0 to - // BLOCK_SIZE_IN_BYTES. We don't want to xform+write them yet, - // because this may have been the last block. The last block gets - // written at Close(). - return; - } - - // We know there are at least 17 bytes, counting those in the current - // buffer, along with the (possibly empty) pending block. - - int bytesRemaining = count; - int curOffset = offset; - - // workitem 12815 - // - // xform chunkwise ... Cannot transform in place using the original - // buffer because that is user-maintained. - - if (_pendingCount != 0) - { - // We have more than one block of data to write, therefore it is safe - // to xform+write. - int fillCount = BLOCK_SIZE_IN_BYTES - _pendingCount; - - // fillCount is possibly zero here. That happens when the pending - // buffer held 16 bytes (one complete block) before this call to - // Write. - if (fillCount > 0) - { - Buffer.BlockCopy(buffer, - offset, - _PendingWriteBlock, - _pendingCount, - fillCount); - - // adjust counts: - bytesRemaining -= fillCount; - curOffset += fillCount; - } - - // xform and write: - WriteTransformOneBlock(_PendingWriteBlock, 0); - _s.Write(_PendingWriteBlock, 0, BLOCK_SIZE_IN_BYTES); - _totalBytesXferred += BLOCK_SIZE_IN_BYTES; - _pendingCount = 0; - } - - // At this point _PendingWriteBlock is empty, and bytesRemaining is - // always greater than 0. - - // Now, xform N blocks, where N = floor((bytesRemaining-1)/16). If - // writing 32 bytes, then xform 1 block, and stage the remaining 16. If - // writing 10037 bytes, xform 627 blocks of 16 bytes, then stage the - // remaining 5 bytes. - - int blocksToXform = (bytesRemaining-1)/BLOCK_SIZE_IN_BYTES; - _pendingCount = bytesRemaining - (blocksToXform * BLOCK_SIZE_IN_BYTES); - - // _pendingCount is ALWAYS between 1 and 16. - // Put the last _pendingCount bytes into the pending block. - Buffer.BlockCopy(buffer, - curOffset + bytesRemaining - _pendingCount, - _PendingWriteBlock, - 0, - _pendingCount); - bytesRemaining -= _pendingCount; - _totalBytesXferred += bytesRemaining; // will be true after the loop - - // now, transform all the full blocks preceding that. - // bytesRemaining is always a multiple of 16 . - if (blocksToXform > 0) - { - do - { - int c = _iobuf.Length; - if (c > bytesRemaining) c = bytesRemaining; - Buffer.BlockCopy(buffer, - curOffset, - _iobuf, - 0, - c); - - WriteTransformBlocks(_iobuf, 0, c); - _s.Write(_iobuf, 0, c); - bytesRemaining -= c; - curOffset += c; - } while(bytesRemaining > 0); - } - } - - - - /// - /// Close the stream. - /// - public override void Close() - { - TraceOutput("Close {0:X8}", this.GetHashCode()); - - // In the degenerate case, no bytes have been written to the - // stream at all. Need to check here, and NOT emit the - // final block if Write has not been called. - if (_pendingCount > 0) - { - WriteTransformFinalBlock(); - _s.Write(_PendingWriteBlock, 0, _pendingCount); - _totalBytesXferred += _pendingCount; - _pendingCount = 0; - } - _s.Close(); - -#if WANT_TRACE - untransformed.Close(); - transformed.Close(); - Console.WriteLine("\nuntransformed bytestream is in {0}", traceFileUntransformed); - Console.WriteLine("\ntransformed bytestream is in {0}", traceFileTransformed); -#endif - TraceOutput("-------------------------------------------------------"); - } - - - /// - /// Returns true if the stream can be read. - /// - public override bool CanRead - { - get - { - if (_mode != CryptoMode.Decrypt) return false; - return true; - } - } - - - /// - /// Always returns false. - /// - public override bool CanSeek - { - get { return false; } - } - - /// - /// Returns true if the CryptoMode is Encrypt. - /// - public override bool CanWrite - { - get { return (_mode == CryptoMode.Encrypt); } - } - - /// - /// Flush the content in the stream. - /// - public override void Flush() - { - _s.Flush(); - } - - /// - /// Getting this property throws a NotImplementedException. - /// - public override long Length - { - get { throw new NotImplementedException(); } - } - - /// - /// Getting or Setting this property throws a NotImplementedException. - /// - public override long Position - { - get { throw new NotImplementedException(); } - set { throw new NotImplementedException(); } - } - - /// - /// This method throws a NotImplementedException. - /// - public override long Seek(long offset, System.IO.SeekOrigin origin) - { - throw new NotImplementedException(); - } - - /// - /// This method throws a NotImplementedException. - /// - public override void SetLength(long value) - { - throw new NotImplementedException(); - } - - - - [System.Diagnostics.ConditionalAttribute("Trace")] - private void TraceOutput(string format, params object[] varParams) - { - lock(_outputLock) - { - int tid = System.Threading.Thread.CurrentThread.GetHashCode(); - Console.ForegroundColor = (ConsoleColor) (tid % 8 + 8); - Console.Write("{0:000} WZACS ", tid); - Console.WriteLine(format, varParams); - Console.ResetColor(); - } - } - - private object _outputLock = new Object(); - } -} -#endif diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipConstants.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipConstants.cs deleted file mode 100644 index cc5eec1a..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipConstants.cs +++ /dev/null @@ -1,51 +0,0 @@ -// ZipConstants.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2006, 2007, 2008, 2009 Dino Chiesa and Microsoft Corporation. -// 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: <2009-August-27 23:22:32> -// -// ------------------------------------------------------------------ -// -// This module defines a few constants that are used in the project. -// -// ------------------------------------------------------------------ - -using System; - -namespace Ionic.Zip -{ - static class ZipConstants - { - public const UInt32 PackedToRemovableMedia = 0x30304b50; - public const UInt32 Zip64EndOfCentralDirectoryRecordSignature = 0x06064b50; - public const UInt32 Zip64EndOfCentralDirectoryLocatorSignature = 0x07064b50; - public const UInt32 EndOfCentralDirectorySignature = 0x06054b50; - public const int ZipEntrySignature = 0x04034b50; - public const int ZipEntryDataDescriptorSignature = 0x08074b50; - public const int SplitArchiveSignature = 0x08074b50; - public const int ZipDirEntrySignature = 0x02014b50; - - - // These are dictated by the Zip Spec.See APPNOTE.txt - public const int AesKeySize = 192; // 128, 192, 256 - public const int AesBlockSize = 128; // ??? - - public const UInt16 AesAlgId128 = 0x660E; - public const UInt16 AesAlgId192 = 0x660F; - public const UInt16 AesAlgId256 = 0x6610; - - } -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipCrypto.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipCrypto.cs deleted file mode 100644 index a8c0b5fc..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipCrypto.cs +++ /dev/null @@ -1,455 +0,0 @@ -// ZipCrypto.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2008, 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-28 06:30:59> -// -// ------------------------------------------------------------------ -// -// This module provides the implementation for "traditional" Zip encryption. -// -// Created Tue Apr 15 17:39:56 2008 -// -// ------------------------------------------------------------------ - -using System; - -namespace Ionic.Zip -{ - /// - /// This class implements the "traditional" or "classic" PKZip encryption, - /// which today is considered to be weak. On the other hand it is - /// ubiquitous. This class is intended for use only by the DotNetZip - /// library. - /// - /// - /// - /// Most uses of the DotNetZip library will not involve direct calls into - /// the ZipCrypto class. Instead, the ZipCrypto class is instantiated and - /// used by the ZipEntry() class when encryption or decryption on an entry - /// is employed. If for some reason you really wanted to use a weak - /// encryption algorithm in some other application, you might use this - /// library. But you would be much better off using one of the built-in - /// strong encryption libraries in the .NET Framework, like the AES - /// algorithm or SHA. - /// - internal class ZipCrypto - { - /// - /// The default constructor for ZipCrypto. - /// - /// - /// - /// This class is intended for internal use by the library only. It's - /// probably not useful to you. Seriously. Stop reading this - /// documentation. It's a waste of your time. Go do something else. - /// Check the football scores. Go get an ice cream with a friend. - /// Seriously. - /// - /// - private ZipCrypto() { } - - public static ZipCrypto ForWrite(string password) - { - ZipCrypto z = new ZipCrypto(); - if (password == null) - throw new BadPasswordException("This entry requires a password."); - z.InitCipher(password); - return z; - } - - - public static ZipCrypto ForRead(string password, ZipEntry e) - { - System.IO.Stream s = e._archiveStream; - e._WeakEncryptionHeader = new byte[12]; - byte[] eh = e._WeakEncryptionHeader; - ZipCrypto z = new ZipCrypto(); - - if (password == null) - throw new BadPasswordException("This entry requires a password."); - - z.InitCipher(password); - - ZipEntry.ReadWeakEncryptionHeader(s, eh); - - // Decrypt the header. This has a side effect of "further initializing the - // encryption keys" in the traditional zip encryption. - byte[] DecryptedHeader = z.DecryptMessage(eh, eh.Length); - - // CRC check - // According to the pkzip spec, the final byte in the decrypted header - // is the highest-order byte in the CRC. We check it here. - if (DecryptedHeader[11] != (byte)((e._Crc32 >> 24) & 0xff)) - { - // In the case that bit 3 of the general purpose bit flag is set to - // indicate the presence of an 'Extended File Header' or a 'data - // descriptor' (signature 0x08074b50), the last byte of the decrypted - // header is sometimes compared with the high-order byte of the - // lastmodified time, rather than the high-order byte of the CRC, to - // verify the password. - // - // This is not documented in the PKWare Appnote.txt. It was - // discovered this by analysis of the Crypt.c source file in the - // InfoZip library http://www.info-zip.org/pub/infozip/ - // - // The reason for this is that the CRC for a file cannot be known - // until the entire contents of the file have been streamed. This - // means a tool would have to read the file content TWICE in its - // entirety in order to perform PKZIP encryption - once to compute - // the CRC, and again to actually encrypt. - // - // This is so important for performance that using the timeblob as - // the verification should be the standard practice for DotNetZip - // when using PKZIP encryption. This implies that bit 3 must be - // set. The downside is that some tools still cannot cope with ZIP - // files that use bit 3. Therefore, DotNetZip DOES NOT force bit 3 - // when PKZIP encryption is in use, and instead, reads the stream - // twice. - // - - if ((e._BitField & 0x0008) != 0x0008) - { - throw new BadPasswordException("The password did not match."); - } - else if (DecryptedHeader[11] != (byte)((e._TimeBlob >> 8) & 0xff)) - { - throw new BadPasswordException("The password did not match."); - } - - // We have a good password. - } - else - { - // A-OK - } - return z; - } - - - - - /// - /// From AppNote.txt: - /// unsigned char decrypt_byte() - /// local unsigned short temp - /// temp :=- Key(2) | 2 - /// decrypt_byte := (temp * (temp ^ 1)) bitshift-right 8 - /// end decrypt_byte - /// - private byte MagicByte - { - get - { - UInt16 t = (UInt16)((UInt16)(_Keys[2] & 0xFFFF) | 2); - return (byte)((t * (t ^ 1)) >> 8); - } - } - - // Decrypting: - // From AppNote.txt: - // loop for i from 0 to 11 - // C := buffer(i) ^ decrypt_byte() - // update_keys(C) - // buffer(i) := C - // end loop - - - /// - /// Call this method on a cipher text to render the plaintext. You must - /// first initialize the cipher with a call to InitCipher. - /// - /// - /// - /// - /// var cipher = new ZipCrypto(); - /// cipher.InitCipher(Password); - /// // Decrypt the header. This has a side effect of "further initializing the - /// // encryption keys" in the traditional zip encryption. - /// byte[] DecryptedMessage = cipher.DecryptMessage(EncryptedMessage); - /// - /// - /// - /// The encrypted buffer. - /// - /// The number of bytes to encrypt. - /// Should be less than or equal to CipherText.Length. - /// - /// - /// The plaintext. - public byte[] DecryptMessage(byte[] cipherText, int length) - { - if (cipherText == null) - throw new ArgumentNullException("cipherText"); - - if (length > cipherText.Length) - throw new ArgumentOutOfRangeException("length", - "Bad length during Decryption: the length parameter must be smaller than or equal to the size of the destination array."); - - byte[] plainText = new byte[length]; - for (int i = 0; i < length; i++) - { - byte C = (byte)(cipherText[i] ^ MagicByte); - UpdateKeys(C); - plainText[i] = C; - } - return plainText; - } - - /// - /// This is the converse of DecryptMessage. It encrypts the plaintext - /// and produces a ciphertext. - /// - /// - /// The plain text buffer. - /// - /// - /// The number of bytes to encrypt. - /// Should be less than or equal to plainText.Length. - /// - /// - /// The ciphertext. - public byte[] EncryptMessage(byte[] plainText, int length) - { - if (plainText == null) - throw new ArgumentNullException("plaintext"); - - if (length > plainText.Length) - throw new ArgumentOutOfRangeException("length", - "Bad length during Encryption: The length parameter must be smaller than or equal to the size of the destination array."); - - byte[] cipherText = new byte[length]; - for (int i = 0; i < length; i++) - { - byte C = plainText[i]; - cipherText[i] = (byte)(plainText[i] ^ MagicByte); - UpdateKeys(C); - } - return cipherText; - } - - - /// - /// This initializes the cipher with the given password. - /// See AppNote.txt for details. - /// - /// - /// - /// The passphrase for encrypting or decrypting with this cipher. - /// - /// - /// - /// - /// 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. - /// - /// - /// - /// - /// After the keys are initialized, then you can use the cipher to - /// encrypt the plaintext. - /// - /// - /// - /// Essentially we encrypt the password with the keys, then discard the - /// ciphertext for the password. This initializes the keys for later use. - /// - /// - /// - public void InitCipher(string passphrase) - { - byte[] p = SharedUtilities.StringToByteArray(passphrase); - for (int i = 0; i < passphrase.Length; i++) - UpdateKeys(p[i]); - } - - - private void UpdateKeys(byte byteValue) - { - _Keys[0] = (UInt32)crc32.ComputeCrc32((int)_Keys[0], byteValue); - _Keys[1] = _Keys[1] + (byte)_Keys[0]; - _Keys[1] = _Keys[1] * 0x08088405 + 1; - _Keys[2] = (UInt32)crc32.ComputeCrc32((int)_Keys[2], (byte)(_Keys[1] >> 24)); - } - - ///// - ///// The byte array representing the seed keys used. - ///// Get this after calling InitCipher. The 12 bytes represents - ///// what the zip spec calls the "EncryptionHeader". - ///// - //public byte[] KeyHeader - //{ - // get - // { - // byte[] result = new byte[12]; - // result[0] = (byte)(_Keys[0] & 0xff); - // result[1] = (byte)((_Keys[0] >> 8) & 0xff); - // result[2] = (byte)((_Keys[0] >> 16) & 0xff); - // result[3] = (byte)((_Keys[0] >> 24) & 0xff); - // result[4] = (byte)(_Keys[1] & 0xff); - // result[5] = (byte)((_Keys[1] >> 8) & 0xff); - // result[6] = (byte)((_Keys[1] >> 16) & 0xff); - // result[7] = (byte)((_Keys[1] >> 24) & 0xff); - // result[8] = (byte)(_Keys[2] & 0xff); - // result[9] = (byte)((_Keys[2] >> 8) & 0xff); - // result[10] = (byte)((_Keys[2] >> 16) & 0xff); - // result[11] = (byte)((_Keys[2] >> 24) & 0xff); - // return result; - // } - //} - - // private fields for the crypto stuff: - private UInt32[] _Keys = { 0x12345678, 0x23456789, 0x34567890 }; - private Ionic.Crc.CRC32 crc32 = new Ionic.Crc.CRC32(); - - } - - internal enum CryptoMode - { - Encrypt, - Decrypt - } - - /// - /// A Stream for reading and concurrently decrypting data from a zip file, - /// or for writing and concurrently encrypting data to a zip file. - /// - internal class ZipCipherStream : System.IO.Stream - { - private ZipCrypto _cipher; - private System.IO.Stream _s; - private CryptoMode _mode; - - /// The constructor. - /// The underlying stream - /// To either encrypt or decrypt. - /// The pre-initialized ZipCrypto object. - public ZipCipherStream(System.IO.Stream s, ZipCrypto cipher, CryptoMode mode) - : base() - { - _cipher = cipher; - _s = s; - _mode = mode; - } - - public override int Read(byte[] buffer, int offset, int count) - { - if (_mode == CryptoMode.Encrypt) - throw new NotSupportedException("This stream does not encrypt via Read()"); - - if (buffer == null) - throw new ArgumentNullException("buffer"); - - byte[] db = new byte[count]; - int n = _s.Read(db, 0, count); - byte[] decrypted = _cipher.DecryptMessage(db, n); - for (int i = 0; i < n; i++) - { - buffer[offset + i] = decrypted[i]; - } - return n; - } - - public override void Write(byte[] buffer, int offset, int count) - { - if (_mode == CryptoMode.Decrypt) - throw new NotSupportedException("This stream does not Decrypt via Write()"); - - if (buffer == null) - throw new ArgumentNullException("buffer"); - - // workitem 7696 - if (count == 0) return; - - byte[] plaintext = null; - if (offset != 0) - { - plaintext = new byte[count]; - for (int i = 0; i < count; i++) - { - plaintext[i] = buffer[offset + i]; - } - } - else plaintext = buffer; - - byte[] encrypted = _cipher.EncryptMessage(plaintext, count); - _s.Write(encrypted, 0, encrypted.Length); - } - - - public override bool CanRead - { - get { return (_mode == CryptoMode.Decrypt); } - } - public override bool CanSeek - { - get { return false; } - } - - public override bool CanWrite - { - get { return (_mode == CryptoMode.Encrypt); } - } - - public override void Flush() - { - //throw new NotSupportedException(); - } - - public override long Length - { - get { throw new NotSupportedException(); } - } - - public override long Position - { - get { throw new NotSupportedException(); } - set { throw new NotSupportedException(); } - } - public override long Seek(long offset, System.IO.SeekOrigin origin) - { - throw new NotSupportedException(); - } - - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - } -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipDirEntry.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipDirEntry.cs deleted file mode 100644 index 882c6941..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipDirEntry.cs +++ /dev/null @@ -1,381 +0,0 @@ -// ZipDirEntry.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2006-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-11 12:03:03> -// -// ------------------------------------------------------------------ -// -// This module defines members of the ZipEntry class for reading the -// Zip file central directory. -// -// Created: Tue, 27 Mar 2007 15:30 -// -// ------------------------------------------------------------------ - - -using System; -using System.Collections.Generic; - -namespace Ionic.Zip -{ - - partial class ZipEntry - { - /// - /// True if the referenced entry is a directory. - /// - internal bool AttributesIndicateDirectory - { - get { return ((_InternalFileAttrs == 0) && ((_ExternalFileAttrs & 0x0010) == 0x0010)); } - } - - - internal void ResetDirEntry() - { - // __FileDataPosition is the position of the file data for an entry. - // It is _RelativeOffsetOfLocalHeader + size of local header. - - // We cannot know the __FileDataPosition until we read the local - // header. - - // The local header is not necessarily the same length as the record - // in the central directory. - - // Set to -1, to indicate we need to read this later. - this.__FileDataPosition = -1; - - // set _LengthOfHeader to 0, to indicate we need to read later. - this._LengthOfHeader = 0; - } - - /// - /// Provides a human-readable string with information about the ZipEntry. - /// - public string Info - { - get - { - var builder = new System.Text.StringBuilder(); - builder - .Append(string.Format(" ZipEntry: {0}\n", this.FileName)) - .Append(string.Format(" Version Made By: {0}\n", this._VersionMadeBy)) - .Append(string.Format(" Needed to extract: {0}\n", this.VersionNeeded)); - - if (this._IsDirectory) - builder.Append(" Entry type: directory\n"); - else - { - builder.Append(string.Format(" File type: {0}\n", this._IsText? "text":"binary")) - .Append(string.Format(" Compression: {0}\n", this.CompressionMethod)) - .Append(string.Format(" Compressed: 0x{0:X}\n", this.CompressedSize)) - .Append(string.Format(" Uncompressed: 0x{0:X}\n", this.UncompressedSize)) - .Append(string.Format(" CRC32: 0x{0:X8}\n", this._Crc32)); - } - builder.Append(string.Format(" Disk Number: {0}\n", this._diskNumber)); - if (this._RelativeOffsetOfLocalHeader > 0xFFFFFFFF) - builder - .Append(string.Format(" Relative Offset: 0x{0:X16}\n", this._RelativeOffsetOfLocalHeader)); - else - builder - .Append(string.Format(" Relative Offset: 0x{0:X8}\n", this._RelativeOffsetOfLocalHeader)); - - builder - .Append(string.Format(" Bit Field: 0x{0:X4}\n", this._BitField)) - .Append(string.Format(" Encrypted?: {0}\n", this._sourceIsEncrypted)) - .Append(string.Format(" Timeblob: 0x{0:X8}\n", this._TimeBlob)) - .Append(string.Format(" Time: {0}\n", Ionic.Zip.SharedUtilities.PackedToDateTime(this._TimeBlob))); - - builder.Append(string.Format(" Is Zip64?: {0}\n", this._InputUsesZip64)); - if (!string.IsNullOrEmpty(this._Comment)) - { - builder.Append(string.Format(" Comment: {0}\n", this._Comment)); - } - builder.Append("\n"); - return builder.ToString(); - } - } - - - // workitem 10330 - private class CopyHelper - { - private static System.Text.RegularExpressions.Regex re = - new System.Text.RegularExpressions.Regex(" \\(copy (\\d+)\\)$"); - - private static int callCount = 0; - - internal static string AppendCopyToFileName(string f) - { - callCount++; - if (callCount > 25) - throw new OverflowException("overflow while creating filename"); - - int n = 1; - int r = f.LastIndexOf("."); - - if (r == -1) - { - // there is no extension - System.Text.RegularExpressions.Match m = re.Match(f); - if (m.Success) - { - n = Int32.Parse(m.Groups[1].Value) + 1; - string copy = String.Format(" (copy {0})", n); - f = f.Substring(0, m.Index) + copy; - } - else - { - string copy = String.Format(" (copy {0})", n); - f = f + copy; - } - } - else - { - //System.Console.WriteLine("HasExtension"); - System.Text.RegularExpressions.Match m = re.Match(f.Substring(0, r)); - if (m.Success) - { - n = Int32.Parse(m.Groups[1].Value) + 1; - string copy = String.Format(" (copy {0})", n); - f = f.Substring(0, m.Index) + copy + f.Substring(r); - } - else - { - string copy = String.Format(" (copy {0})", n); - f = f.Substring(0, r) + copy + f.Substring(r); - } - - //System.Console.WriteLine("returning f({0})", f); - } - return f; - } - } - - - - /// - /// Reads one entry from the zip directory structure in the zip file. - /// - /// - /// - /// The zipfile for which a directory entry will be read. From this param, the - /// method gets the ReadStream and the expected text encoding - /// (ProvisionalAlternateEncoding) which is used if the entry is not marked - /// UTF-8. - /// - /// - /// - /// a list of previously seen entry names; used to prevent duplicates. - /// - /// - /// the entry read from the archive. - internal static ZipEntry ReadDirEntry(ZipFile zf, - Dictionary previouslySeen) - { - System.IO.Stream s = zf.ReadStream; - System.Text.Encoding expectedEncoding = (zf.AlternateEncodingUsage == ZipOption.Always) - ? zf.AlternateEncoding - : ZipFile.DefaultEncoding; - - int signature = Ionic.Zip.SharedUtilities.ReadSignature(s); - // return null if this is not a local file header signature - if (IsNotValidZipDirEntrySig(signature)) - { - s.Seek(-4, System.IO.SeekOrigin.Current); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(s); - - // Getting "not a ZipDirEntry signature" here is not always wrong or an - // error. This can happen when walking through a zipfile. After the - // last ZipDirEntry, we expect to read an - // EndOfCentralDirectorySignature. When we get this is how we know - // we've reached the end of the central directory. - if (signature != ZipConstants.EndOfCentralDirectorySignature && - signature != ZipConstants.Zip64EndOfCentralDirectoryRecordSignature && - signature != ZipConstants.ZipEntrySignature // workitem 8299 - ) - { - throw new BadReadException(String.Format(" Bad signature (0x{0:X8}) at position 0x{1:X8}", signature, s.Position)); - } - return null; - } - - int bytesRead = 42 + 4; - byte[] block = new byte[42]; - int n = s.Read(block, 0, block.Length); - if (n != block.Length) return null; - - int i = 0; - ZipEntry zde = new ZipEntry(); - zde.AlternateEncoding = expectedEncoding; - zde._Source = ZipEntrySource.ZipFile; - zde._container = new ZipContainer(zf); - - unchecked - { - zde._VersionMadeBy = (short)(block[i++] + block[i++] * 256); - zde._VersionNeeded = (short)(block[i++] + block[i++] * 256); - zde._BitField = (short)(block[i++] + block[i++] * 256); - zde._CompressionMethod = (Int16)(block[i++] + block[i++] * 256); - zde._TimeBlob = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256; - zde._LastModified = Ionic.Zip.SharedUtilities.PackedToDateTime(zde._TimeBlob); - zde._timestamp |= ZipEntryTimestamp.DOS; - - zde._Crc32 = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256; - zde._CompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256); - zde._UncompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256); - } - - // preserve - zde._CompressionMethod_FromZipFile = zde._CompressionMethod; - - zde._filenameLength = (short)(block[i++] + block[i++] * 256); - zde._extraFieldLength = (short)(block[i++] + block[i++] * 256); - zde._commentLength = (short)(block[i++] + block[i++] * 256); - zde._diskNumber = (UInt32)(block[i++] + block[i++] * 256); - - zde._InternalFileAttrs = (short)(block[i++] + block[i++] * 256); - zde._ExternalFileAttrs = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256; - - zde._RelativeOffsetOfLocalHeader = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256); - - // workitem 7801 - zde.IsText = ((zde._InternalFileAttrs & 0x01) == 0x01); - - block = new byte[zde._filenameLength]; - n = s.Read(block, 0, block.Length); - bytesRead += n; - if ((zde._BitField & 0x0800) == 0x0800) - { - // UTF-8 is in use - zde._FileNameInArchive = Ionic.Zip.SharedUtilities.Utf8StringFromBuffer(block); - } - else - { - zde._FileNameInArchive = Ionic.Zip.SharedUtilities.StringFromBuffer(block, expectedEncoding); - } - - // workitem 10330 - // insure unique entry names - while (previouslySeen.ContainsKey(zde._FileNameInArchive)) - { - zde._FileNameInArchive = CopyHelper.AppendCopyToFileName(zde._FileNameInArchive); - zde._metadataChanged = true; - } - - if (zde.AttributesIndicateDirectory) - zde.MarkAsDirectory(); // may append a slash to filename if nec. - // workitem 6898 - else if (zde._FileNameInArchive.EndsWith("/")) zde.MarkAsDirectory(); - - zde._CompressedFileDataSize = zde._CompressedSize; - if ((zde._BitField & 0x01) == 0x01) - { - // this may change after processing the Extra field - zde._Encryption_FromZipFile = zde._Encryption = - EncryptionAlgorithm.PkzipWeak; - zde._sourceIsEncrypted = true; - } - - if (zde._extraFieldLength > 0) - { - zde._InputUsesZip64 = (zde._CompressedSize == 0xFFFFFFFF || - zde._UncompressedSize == 0xFFFFFFFF || - zde._RelativeOffsetOfLocalHeader == 0xFFFFFFFF); - - // Console.WriteLine(" Input uses Z64?: {0}", zde._InputUsesZip64); - - bytesRead += zde.ProcessExtraField(s, zde._extraFieldLength); - zde._CompressedFileDataSize = zde._CompressedSize; - } - - // we've processed the extra field, so we know the encryption method is set now. - if (zde._Encryption == EncryptionAlgorithm.PkzipWeak) - { - // the "encryption header" of 12 bytes precedes the file data - zde._CompressedFileDataSize -= 12; - } -#if AESCRYPTO - else if (zde.Encryption == EncryptionAlgorithm.WinZipAes128 || - zde.Encryption == EncryptionAlgorithm.WinZipAes256) - { - zde._CompressedFileDataSize = zde.CompressedSize - - (ZipEntry.GetLengthOfCryptoHeaderBytes(zde.Encryption) + 10); - zde._LengthOfTrailer = 10; - } -#endif - - // tally the trailing descriptor - if ((zde._BitField & 0x0008) == 0x0008) - { - // sig, CRC, Comp and Uncomp sizes - if (zde._InputUsesZip64) - zde._LengthOfTrailer += 24; - else - zde._LengthOfTrailer += 16; - } - - // workitem 12744 - zde.AlternateEncoding = ((zde._BitField & 0x0800) == 0x0800) - ? System.Text.Encoding.UTF8 - :expectedEncoding; - - zde.AlternateEncodingUsage = ZipOption.Always; - - if (zde._commentLength > 0) - { - block = new byte[zde._commentLength]; - n = s.Read(block, 0, block.Length); - bytesRead += n; - if ((zde._BitField & 0x0800) == 0x0800) - { - // UTF-8 is in use - zde._Comment = Ionic.Zip.SharedUtilities.Utf8StringFromBuffer(block); - } - else - { - zde._Comment = Ionic.Zip.SharedUtilities.StringFromBuffer(block, expectedEncoding); - } - } - //zde._LengthOfDirEntry = bytesRead; - return zde; - } - - - /// - /// Returns true if the passed-in value is a valid signature for a ZipDirEntry. - /// - /// the candidate 4-byte signature value. - /// true, if the signature is valid according to the PKWare spec. - internal static bool IsNotValidZipDirEntrySig(int signature) - { - return (signature != ZipConstants.ZipDirEntrySignature); - } - - - private Int16 _VersionMadeBy; - private Int16 _InternalFileAttrs; - private Int32 _ExternalFileAttrs; - - //private Int32 _LengthOfDirEntry; - private Int16 _filenameLength; - private Int16 _extraFieldLength; - private Int16 _commentLength; - } - - -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntry.Extract.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntry.Extract.cs deleted file mode 100644 index 17117db1..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntry.Extract.cs +++ /dev/null @@ -1,1456 +0,0 @@ -// ZipEntry.Extract.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-August-06 18:08:21> -// -// ------------------------------------------------------------------ -// -// This module defines logic for Extract methods on the ZipEntry class. -// -// ------------------------------------------------------------------ - - -using System; -using System.IO; - -namespace Ionic.Zip -{ - - public partial class ZipEntry - { - /// - /// Extract the entry to the filesystem, starting at the current - /// working directory. - /// - /// - /// - /// This method has a bunch of overloads! One of them is sure to - /// be the right one for you... If you don't like these, check - /// out the ExtractWithPassword() methods. - /// - /// - /// - /// - /// - /// - /// - /// - /// This method extracts an entry from a zip file into the current - /// working directory. The path of the entry as extracted is the full - /// path as specified in the zip archive, relative to the current - /// working directory. After the file is extracted successfully, the - /// file attributes and timestamps are set. - /// - /// - /// - /// The action taken when extraction an entry would overwrite an - /// existing file is determined by the property. - /// - /// - /// - /// Within the call to Extract(), the content for the entry is - /// written into a filesystem file, and then the last modified time of the - /// file is set according to the property on - /// the entry. See the remarks the property for - /// some details about the last modified time. - /// - /// - /// - public void Extract() - { - InternalExtract(".", null, null); - } - - - /// - /// Extract the entry to a file in the filesystem, using the specified - /// behavior when extraction would overwrite an existing file. - /// - /// - /// - /// - /// See the remarks on the property, for some - /// details about how the last modified time of the file is set after - /// extraction. - /// - /// - /// - /// - /// The action to take if extraction would overwrite an existing file. - /// - public void Extract(ExtractExistingFileAction extractExistingFile) - { - ExtractExistingFile = extractExistingFile; - InternalExtract(".", null, null); - } - - /// - /// Extracts the entry to the specified stream. - /// - /// - /// - /// - /// The caller can specify any write-able stream, for example a , a , or ASP.NET's - /// Response.OutputStream. The content will be decrypted and - /// decompressed as necessary. If the entry is encrypted and no password - /// is provided, this method will throw. - /// - /// - /// The position on the stream is not reset by this method before it extracts. - /// You may want to call stream.Seek() before calling ZipEntry.Extract(). - /// - /// - /// - /// - /// the stream to which the entry should be extracted. - /// - /// - public void Extract(Stream stream) - { - InternalExtract(null, stream, null); - } - - /// - /// Extract the entry to the filesystem, starting at the specified base - /// directory. - /// - /// - /// the pathname of the base directory - /// - /// - /// - /// - /// - /// This example extracts only the entries in a zip file that are .txt files, - /// into a directory called "textfiles". - /// - /// using (ZipFile zip = ZipFile.Read("PackedDocuments.zip")) - /// { - /// foreach (string s1 in zip.EntryFilenames) - /// { - /// if (s1.EndsWith(".txt")) - /// { - /// zip[s1].Extract("textfiles"); - /// } - /// } - /// } - /// - /// - /// 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 - /// - /// - /// - /// - /// - /// - /// Using this method, existing entries in the filesystem will not be - /// overwritten. If you would like to force the overwrite of existing - /// files, see the property, or call - /// . - /// - /// - /// - /// See the remarks on the property, for some - /// details about how the last modified time of the created file is set. - /// - /// - public void Extract(string baseDirectory) - { - InternalExtract(baseDirectory, null, null); - } - - - - - - /// - /// Extract the entry to the filesystem, starting at the specified base - /// directory, and using the specified behavior when extraction would - /// overwrite an existing file. - /// - /// - /// - /// - /// See the remarks on the property, for some - /// details about how the last modified time of the created file is set. - /// - /// - /// - /// - /// - /// String sZipPath = "Airborne.zip"; - /// String sFilePath = "Readme.txt"; - /// String sRootFolder = "Digado"; - /// using (ZipFile zip = ZipFile.Read(sZipPath)) - /// { - /// if (zip.EntryFileNames.Contains(sFilePath)) - /// { - /// // use the string indexer on the zip file - /// zip[sFileName].Extract(sRootFolder, - /// ExtractExistingFileAction.OverwriteSilently); - /// } - /// } - /// - /// - /// - /// Dim sZipPath as String = "Airborne.zip" - /// Dim sFilePath As String = "Readme.txt" - /// Dim sRootFolder As String = "Digado" - /// Using zip As ZipFile = ZipFile.Read(sZipPath) - /// If zip.EntryFileNames.Contains(sFilePath) - /// ' use the string indexer on the zip file - /// zip(sFilePath).Extract(sRootFolder, _ - /// ExtractExistingFileAction.OverwriteSilently) - /// End If - /// End Using - /// - /// - /// - /// the pathname of the base directory - /// - /// The action to take if extraction would overwrite an existing file. - /// - public void Extract(string baseDirectory, ExtractExistingFileAction extractExistingFile) - { - ExtractExistingFile = extractExistingFile; - InternalExtract(baseDirectory, null, null); - } - - - /// - /// Extract the entry to the filesystem, using the current working directory - /// and the specified password. - /// - /// - /// - /// This method has a bunch of overloads! One of them is sure to be - /// the right one for you... - /// - /// - /// - /// - /// - /// - /// - /// - /// Existing entries in the filesystem will not be overwritten. If you - /// would like to force the overwrite of existing files, see the property, or call - /// . - /// - /// - /// - /// See the remarks on the property for some - /// details about how the "last modified" time of the created file is - /// set. - /// - /// - /// - /// - /// In this example, entries that use encryption are extracted using a - /// particular password. - /// - /// using (var zip = ZipFile.Read(FilePath)) - /// { - /// foreach (ZipEntry e in zip) - /// { - /// if (e.UsesEncryption) - /// e.ExtractWithPassword("Secret!"); - /// else - /// e.Extract(); - /// } - /// } - /// - /// - /// Using zip As ZipFile = ZipFile.Read(FilePath) - /// Dim e As ZipEntry - /// For Each e In zip - /// If (e.UsesEncryption) - /// e.ExtractWithPassword("Secret!") - /// Else - /// e.Extract - /// End If - /// Next - /// End Using - /// - /// - /// The Password to use for decrypting the entry. - public void ExtractWithPassword(string password) - { - InternalExtract(".", null, password); - } - - /// - /// Extract the entry to the filesystem, starting at the specified base - /// directory, and using the specified password. - /// - /// - /// - /// - /// - /// - /// - /// Existing entries in the filesystem will not be overwritten. If you - /// would like to force the overwrite of existing files, see the property, or call - /// . - /// - /// - /// - /// See the remarks on the property, for some - /// details about how the last modified time of the created file is set. - /// - /// - /// - /// The pathname of the base directory. - /// The Password to use for decrypting the entry. - public void ExtractWithPassword(string baseDirectory, string password) - { - InternalExtract(baseDirectory, null, password); - } - - - - - /// - /// Extract the entry to a file in the filesystem, relative to the - /// current directory, using the specified behavior when extraction - /// would overwrite an existing file. - /// - /// - /// - /// - /// See the remarks on the property, for some - /// details about how the last modified time of the created file is set. - /// - /// - /// - /// The Password to use for decrypting the entry. - /// - /// - /// The action to take if extraction would overwrite an existing file. - /// - public void ExtractWithPassword(ExtractExistingFileAction extractExistingFile, string password) - { - ExtractExistingFile = extractExistingFile; - InternalExtract(".", null, password); - } - - - - /// - /// Extract the entry to the filesystem, starting at the specified base - /// directory, and using the specified behavior when extraction would - /// overwrite an existing file. - /// - /// - /// - /// See the remarks on the property, for some - /// details about how the last modified time of the created file is set. - /// - /// - /// the pathname of the base directory - /// - /// The action to take if extraction would - /// overwrite an existing file. - /// - /// The Password to use for decrypting the entry. - public void ExtractWithPassword(string baseDirectory, ExtractExistingFileAction extractExistingFile, string password) - { - ExtractExistingFile = extractExistingFile; - InternalExtract(baseDirectory, null, password); - } - - /// - /// Extracts the entry to the specified stream, using the specified - /// Password. For example, the caller could extract to Console.Out, or - /// to a MemoryStream. - /// - /// - /// - /// - /// The caller can specify any write-able stream, for example a , a , or ASP.NET's - /// Response.OutputStream. The content will be decrypted and - /// decompressed as necessary. If the entry is encrypted and no password - /// is provided, this method will throw. - /// - /// - /// The position on the stream is not reset by this method before it extracts. - /// You may want to call stream.Seek() before calling ZipEntry.Extract(). - /// - /// - /// - /// - /// - /// the stream to which the entry should be extracted. - /// - /// - /// The password to use for decrypting the entry. - /// - public void ExtractWithPassword(Stream stream, string password) - { - InternalExtract(null, stream, password); - } - - - /// - /// Opens a readable stream corresponding to the zip entry in the - /// archive. The stream decompresses and decrypts as necessary, as it - /// is read. - /// - /// - /// - /// - /// - /// DotNetZip offers a variety of ways to extract entries from a zip - /// file. This method allows an application to extract an entry by - /// reading a . - /// - /// - /// - /// The return value is of type . Use it as you would any - /// stream for reading. When an application calls on that stream, it will - /// receive data from the zip entry that is decrypted and decompressed - /// as necessary. - /// - /// - /// - /// CrcCalculatorStream adds one additional feature: it keeps a - /// CRC32 checksum on the bytes of the stream as it is read. The CRC - /// value is available in the property on the - /// CrcCalculatorStream. When the read is complete, your - /// application - /// should check this CRC against the - /// property on the ZipEntry to validate the content of the - /// ZipEntry. You don't have to validate the entry using the CRC, but - /// you should, to verify integrity. Check the example for how to do - /// this. - /// - /// - /// - /// If the entry is protected with a password, then you need to provide - /// a password prior to calling , either by - /// setting the property on the entry, or the - /// property on the ZipFile - /// itself. Or, you can use , the - /// overload of OpenReader that accepts a password parameter. - /// - /// - /// - /// If you want to extract entry data into a write-able stream that is - /// already opened, like a , do not - /// use this method. Instead, use . - /// - /// - /// - /// Your application may use only one stream created by OpenReader() at - /// a time, and you should not call other Extract methods before - /// completing your reads on a stream obtained from OpenReader(). This - /// is because there is really only one source stream for the compressed - /// content. A call to OpenReader() seeks in the source stream, to the - /// beginning of the compressed content. A subsequent call to - /// OpenReader() on a different entry will seek to a different position - /// in the source stream, as will a call to Extract() or one of its - /// overloads. This will corrupt the state for the decompressing stream - /// from the original call to OpenReader(). - /// - /// - /// - /// The OpenReader() method works only when the ZipEntry is - /// obtained from an instance of ZipFile. This method will throw - /// an exception if the ZipEntry is obtained from a . - /// - /// - /// - /// - /// This example shows how to open a zip archive, then read in a named - /// entry via a stream. After the read loop is complete, the code - /// compares the calculated during the read loop with the expected CRC - /// on the ZipEntry, to verify the extraction. - /// - /// using (ZipFile zip = new ZipFile(ZipFileToRead)) - /// { - /// ZipEntry e1= zip["Elevation.mp3"]; - /// using (Ionic.Zlib.CrcCalculatorStream s = e1.OpenReader()) - /// { - /// byte[] buffer = new byte[4096]; - /// int n, totalBytesRead= 0; - /// do { - /// n = s.Read(buffer,0, buffer.Length); - /// totalBytesRead+=n; - /// } while (n>0); - /// if (s.Crc32 != e1.Crc32) - /// throw new Exception(string.Format("The Zip Entry failed the CRC Check. (0x{0:X8}!=0x{1:X8})", s.Crc32, e1.Crc32)); - /// if (totalBytesRead != e1.UncompressedSize) - /// throw new Exception(string.Format("We read an unexpected number of bytes. ({0}!={1})", totalBytesRead, e1.UncompressedSize)); - /// } - /// } - /// - /// - /// Using zip As New ZipFile(ZipFileToRead) - /// Dim e1 As ZipEntry = zip.Item("Elevation.mp3") - /// Using s As Ionic.Zlib.CrcCalculatorStream = e1.OpenReader - /// Dim n As Integer - /// Dim buffer As Byte() = New Byte(4096) {} - /// Dim totalBytesRead As Integer = 0 - /// Do - /// n = s.Read(buffer, 0, buffer.Length) - /// totalBytesRead = (totalBytesRead + n) - /// Loop While (n > 0) - /// If (s.Crc32 <> e1.Crc32) Then - /// Throw New Exception(String.Format("The Zip Entry failed the CRC Check. (0x{0:X8}!=0x{1:X8})", s.Crc32, e1.Crc32)) - /// End If - /// If (totalBytesRead <> e1.UncompressedSize) Then - /// Throw New Exception(String.Format("We read an unexpected number of bytes. ({0}!={1})", totalBytesRead, e1.UncompressedSize)) - /// End If - /// End Using - /// End Using - /// - /// - /// - /// The Stream for reading. - public Ionic.Crc.CrcCalculatorStream OpenReader() - { - // workitem 10923 - if (_container.ZipFile == null) - throw new InvalidOperationException("Use OpenReader() only with ZipFile."); - - // use the entry password if it is non-null, - // else use the zipfile password, which is possibly null - return InternalOpenReader(this._Password ?? this._container.Password); - } - - /// - /// Opens a readable stream for an encrypted zip entry in the archive. - /// The stream decompresses and decrypts as necessary, as it is read. - /// - /// - /// - /// - /// See the documentation on the method for - /// full details. This overload allows the application to specify a - /// password for the ZipEntry to be read. - /// - /// - /// - /// The password to use for decrypting the entry. - /// The Stream for reading. - public Ionic.Crc.CrcCalculatorStream OpenReader(string password) - { - // workitem 10923 - if (_container.ZipFile == null) - throw new InvalidOperationException("Use OpenReader() only with ZipFile."); - - return InternalOpenReader(password); - } - - - - internal Ionic.Crc.CrcCalculatorStream InternalOpenReader(string password) - { - ValidateCompression(); - ValidateEncryption(); - SetupCryptoForExtract(password); - - // workitem 7958 - if (this._Source != ZipEntrySource.ZipFile) - throw new BadStateException("You must call ZipFile.Save before calling OpenReader"); - - // LeftToRead is a count of bytes remaining to be read (out) - // from the stream AFTER decompression and decryption. - // It is the uncompressed size, unless ... there is no compression in which - // case ...? :< I'm not sure why it's not always UncompressedSize - Int64 LeftToRead = (_CompressionMethod_FromZipFile == (short)CompressionMethod.None) - ? this._CompressedFileDataSize - : this.UncompressedSize; - - Stream input = this.ArchiveStream; - - this.ArchiveStream.Seek(this.FileDataPosition, SeekOrigin.Begin); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream); - - _inputDecryptorStream = GetExtractDecryptor(input); - Stream input3 = GetExtractDecompressor(_inputDecryptorStream); - - return new Ionic.Crc.CrcCalculatorStream(input3, LeftToRead); - } - - - - private void OnExtractProgress(Int64 bytesWritten, Int64 totalBytesToWrite) - { - if (_container.ZipFile != null) - _ioOperationCanceled = _container.ZipFile.OnExtractBlock(this, bytesWritten, totalBytesToWrite); - } - - - private void OnBeforeExtract(string path) - { - // When in the context of a ZipFile.ExtractAll, the events are generated from - // the ZipFile method, not from within the ZipEntry instance. (why?) - // Therefore we suppress the events originating from the ZipEntry method. - if (_container.ZipFile != null) - { - if (!_container.ZipFile._inExtractAll) - { - _ioOperationCanceled = _container.ZipFile.OnSingleEntryExtract(this, path, true); - } - } - } - - private void OnAfterExtract(string path) - { - // When in the context of a ZipFile.ExtractAll, the events are generated from - // the ZipFile method, not from within the ZipEntry instance. (why?) - // Therefore we suppress the events originating from the ZipEntry method. - if (_container.ZipFile != null) - { - if (!_container.ZipFile._inExtractAll) - { - _container.ZipFile.OnSingleEntryExtract(this, path, false); - } - } - } - - private void OnExtractExisting(string path) - { - if (_container.ZipFile != null) - _ioOperationCanceled = _container.ZipFile.OnExtractExisting(this, path); - } - - private static void ReallyDelete(string fileName) - { - // workitem 7881 - // reset ReadOnly bit if necessary -#if NETCF - if ( (NetCfFile.GetAttributes(fileName) & (uint)FileAttributes.ReadOnly) == (uint)FileAttributes.ReadOnly) - NetCfFile.SetAttributes(fileName, (uint)FileAttributes.Normal); -#elif SILVERLIGHT -#else - if ((File.GetAttributes(fileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) - File.SetAttributes(fileName, FileAttributes.Normal); -#endif - File.Delete(fileName); - } - - - private void WriteStatus(string format, params Object[] args) - { - if (_container.ZipFile != null && _container.ZipFile.Verbose) _container.ZipFile.StatusMessageTextWriter.WriteLine(format, args); - } - - - // Pass in either basedir or s, but not both. - // In other words, you can extract to a stream or to a directory (filesystem), but not both! - // The Password param is required for encrypted entries. - private void InternalExtract(string baseDir, Stream outstream, string password) - { - // workitem 7958 - if (_container == null) - throw new BadStateException("This entry is an orphan"); - - // workitem 10355 - if (_container.ZipFile == null) - throw new InvalidOperationException("Use Extract() only with ZipFile."); - - _container.ZipFile.Reset(false); - - if (this._Source != ZipEntrySource.ZipFile) - throw new BadStateException("You must call ZipFile.Save before calling any Extract method"); - - OnBeforeExtract(baseDir); - _ioOperationCanceled = false; - string targetFileName = null; - Stream output = null; - bool fileExistsBeforeExtraction = false; - bool checkLaterForResetDirTimes = false; - try - { - ValidateCompression(); - ValidateEncryption(); - - if (ValidateOutput(baseDir, outstream, out targetFileName)) - { - WriteStatus("extract dir {0}...", targetFileName); - // if true, then the entry was a directory and has been created. - // We need to fire the Extract Event. - OnAfterExtract(baseDir); - return; - } - - // workitem 10639 - // do we want to extract to a regular filesystem file? - if (targetFileName != null) - { - // Check for extracting to a previously extant file. The user - // can specify bejavior for that case: overwrite, don't - // overwrite, and throw. Also, if the file exists prior to - // extraction, it affects exception handling: whether to delete - // the target of extraction or not. This check needs to be done - // before the password check is done, because password check may - // throw a BadPasswordException, which triggers the catch, - // wherein the extant file may be deleted if not flagged as - // pre-existing. - if (File.Exists(targetFileName)) - { - fileExistsBeforeExtraction = true; - int rc = CheckExtractExistingFile(baseDir, targetFileName); - if (rc == 2) goto ExitTry; // cancel - if (rc == 1) return; // do not overwrite - } - } - - // If no password explicitly specified, use the password on the entry itself, - // or on the zipfile itself. - string p = password ?? this._Password ?? this._container.Password; - if (_Encryption_FromZipFile != EncryptionAlgorithm.None) - { - if (p == null) - throw new BadPasswordException(); - SetupCryptoForExtract(p); - } - - - // set up the output stream - if (targetFileName != null) - { - WriteStatus("extract file {0}...", targetFileName); - targetFileName += ".tmp"; - var dirName = Path.GetDirectoryName(targetFileName); - // ensure the target path exists - if (!Directory.Exists(dirName)) - { - // we create the directory here, but we do not set the - // create/modified/accessed times on it because it is being - // created implicitly, not explcitly. There's no entry in the - // zip archive for the directory. - Directory.CreateDirectory(dirName); - } - else - { - // workitem 8264 - if (_container.ZipFile != null) - checkLaterForResetDirTimes = _container.ZipFile._inExtractAll; - } - - // File.Create(CreateNew) will overwrite any existing file. - output = new FileStream(targetFileName, FileMode.CreateNew); - } - else - { - WriteStatus("extract entry {0} to stream...", FileName); - output = outstream; - } - - - if (_ioOperationCanceled) - goto ExitTry; - - Int32 ActualCrc32 = ExtractOne(output); - - if (_ioOperationCanceled) - goto ExitTry; - - VerifyCrcAfterExtract(ActualCrc32); - - if (targetFileName != null) - { - output.Close(); - output = null; - - // workitem 10639 - // move file to permanent home - string tmpName = targetFileName; - string zombie = null; - targetFileName = tmpName.Substring(0,tmpName.Length-4); - - if (fileExistsBeforeExtraction) - { - // An AV program may hold the target file open, which means - // File.Delete() will succeed, though the actual deletion - // remains pending. This will prevent a subsequent - // File.Move() from succeeding. To avoid this, when the file - // already exists, we need to replace it in 3 steps: - // - // 1. rename the existing file to a zombie name; - // 2. rename the extracted file from the temp name to - // the target file name; - // 3. delete the zombie. - // - zombie = targetFileName + ".PendingOverwrite"; - File.Move(targetFileName, zombie); - } - - File.Move(tmpName, targetFileName); - _SetTimes(targetFileName, true); - - if (zombie != null && File.Exists(zombie)) - ReallyDelete(zombie); - - // workitem 8264 - if (checkLaterForResetDirTimes) - { - // This is sort of a hack. What I do here is set the time on - // the parent directory, every time a file is extracted into - // it. If there is a directory with 1000 files, then I set - // the time on the dir, 1000 times. This allows the directory - // to have times that reflect the actual time on the entry in - // the zip archive. - - // String.Contains is not available on .NET CF 2.0 - if (this.FileName.IndexOf('/') != -1) - { - string dirname = Path.GetDirectoryName(this.FileName); - if (this._container.ZipFile[dirname] == null) - { - _SetTimes(Path.GetDirectoryName(targetFileName), false); - } - } - } - -#if NETCF - // workitem 7926 - version made by OS can be zero or 10 - if ((_VersionMadeBy & 0xFF00) == 0x0a00 || (_VersionMadeBy & 0xFF00) == 0x0000) - NetCfFile.SetAttributes(targetFileName, (uint)_ExternalFileAttrs); - -#else - // workitem 7071 - // - // We can only apply attributes if they are relevant to the NTFS - // OS. Must do this LAST because it may involve a ReadOnly bit, - // which would prevent us from setting the time, etc. - // - // workitem 7926 - version made by OS can be zero (FAT) or 10 - // (NTFS) - if ((_VersionMadeBy & 0xFF00) == 0x0a00 || (_VersionMadeBy & 0xFF00) == 0x0000) - File.SetAttributes(targetFileName, (FileAttributes)_ExternalFileAttrs); -#endif - } - - OnAfterExtract(baseDir); - - ExitTry: ; - } - catch (Exception) - { - _ioOperationCanceled = true; - throw; - } - finally - { - if (_ioOperationCanceled) - { - if (targetFileName != null) - { - try - { - if (output != null) output.Close(); - // An exception has occurred. If the file exists, check - // to see if it existed before we tried extracting. If - // it did not, attempt to remove the target file. There - // is a small possibility that the existing file has - // been extracted successfully, overwriting a previously - // existing file, and an exception was thrown after that - // but before final completion (setting times, etc). In - // that case the file will remain, even though some - // error occurred. Nothing to be done about it. - if (File.Exists(targetFileName) && !fileExistsBeforeExtraction) - File.Delete(targetFileName); - - } - finally { } - } - } - } - } - - -#if NOT - internal void CalcWinZipAesMac(Stream input) - { - if (Encryption == EncryptionAlgorithm.WinZipAes128 || - Encryption == EncryptionAlgorithm.WinZipAes256) - { - if (input is WinZipAesCipherStream) - wzs = input as WinZipAesCipherStream; - - else if (input is Ionic.Zlib.CrcCalculatorStream) - { - xxx; - } - - } - } -#endif - - - internal void VerifyCrcAfterExtract(Int32 actualCrc32) - { - -#if AESCRYPTO - // After extracting, Validate the CRC32 - if (actualCrc32 != _Crc32) - { - // CRC is not meaningful with WinZipAES and AES method 2 (AE-2) - if ((Encryption != EncryptionAlgorithm.WinZipAes128 && - Encryption != EncryptionAlgorithm.WinZipAes256) - || _WinZipAesMethod != 0x02) - throw new BadCrcException("CRC error: the file being extracted appears to be corrupted. " + - String.Format("Expected 0x{0:X8}, Actual 0x{1:X8}", _Crc32, actualCrc32)); - } - - // ignore MAC if the size of the file is zero - if (this.UncompressedSize == 0) - return; - - // calculate the MAC - if (Encryption == EncryptionAlgorithm.WinZipAes128 || - Encryption == EncryptionAlgorithm.WinZipAes256) - { - WinZipAesCipherStream wzs = _inputDecryptorStream as WinZipAesCipherStream; - _aesCrypto_forExtract.CalculatedMac = wzs.FinalAuthentication; - - _aesCrypto_forExtract.ReadAndVerifyMac(this.ArchiveStream); // throws if MAC is bad - // side effect: advances file position. - } - - - - -#else - if (actualCrc32 != _Crc32) - throw new BadCrcException("CRC error: the file being extracted appears to be corrupted. " + - String.Format("Expected 0x{0:X8}, Actual 0x{1:X8}", _Crc32, actualCrc32)); -#endif - } - - - - - private int CheckExtractExistingFile(string baseDir, string targetFileName) - { - int loop = 0; - // returns: 0 == extract, 1 = don't, 2 = cancel - do - { - switch (ExtractExistingFile) - { - case ExtractExistingFileAction.OverwriteSilently: - WriteStatus("the file {0} exists; will overwrite it...", targetFileName); - return 0; - - case ExtractExistingFileAction.DoNotOverwrite: - WriteStatus("the file {0} exists; not extracting entry...", FileName); - OnAfterExtract(baseDir); - return 1; - - case ExtractExistingFileAction.InvokeExtractProgressEvent: - if (loop>0) - throw new ZipException(String.Format("The file {0} already exists.", targetFileName)); - OnExtractExisting(baseDir); - if (_ioOperationCanceled) - return 2; - - // loop around - break; - - case ExtractExistingFileAction.Throw: - default: - throw new ZipException(String.Format("The file {0} already exists.", targetFileName)); - } - loop++; - } - while (true); - } - - - - - private void _CheckRead(int nbytes) - { - if (nbytes == 0) - throw new BadReadException(String.Format("bad read of entry {0} from compressed archive.", - this.FileName)); - } - - - private Stream _inputDecryptorStream; - - private Int32 ExtractOne(Stream output) - { - Int32 CrcResult = 0; - Stream input = this.ArchiveStream; - - try - { - // change for workitem 8098 - input.Seek(this.FileDataPosition, SeekOrigin.Begin); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(input); - - byte[] bytes = new byte[BufferSize]; - - // The extraction process varies depending on how the entry was - // stored. It could have been encrypted, and it coould have - // been compressed, or both, or neither. So we need to check - // both the encryption flag and the compression flag, and take - // the proper action in all cases. - - Int64 LeftToRead = (_CompressionMethod_FromZipFile != (short)CompressionMethod.None) - ? this.UncompressedSize - : this._CompressedFileDataSize; - - // Get a stream that either decrypts or not. - _inputDecryptorStream = GetExtractDecryptor(input); - - Stream input3 = GetExtractDecompressor( _inputDecryptorStream ); - - Int64 bytesWritten = 0; - // As we read, we maybe decrypt, and then we maybe decompress. Then we write. - using (var s1 = new Ionic.Crc.CrcCalculatorStream(input3)) - { - while (LeftToRead > 0) - { - //Console.WriteLine("ExtractOne: LeftToRead {0}", LeftToRead); - - // Casting LeftToRead down to an int is ok here in the else clause, - // because that only happens when it is less than bytes.Length, - // which is much less than MAX_INT. - int len = (LeftToRead > bytes.Length) ? bytes.Length : (int)LeftToRead; - int n = s1.Read(bytes, 0, len); - - // must check data read - essential for detecting corrupt zip files - _CheckRead(n); - - output.Write(bytes, 0, n); - LeftToRead -= n; - bytesWritten += n; - - // fire the progress event, check for cancels - OnExtractProgress(bytesWritten, UncompressedSize); - if (_ioOperationCanceled) - { - break; - } - } - - CrcResult = s1.Crc; - } - } - finally - { - var zss = input as ZipSegmentedStream; - if (zss != null) - { -#if NETCF - zss.Close(); -#else - // need to dispose it - zss.Dispose(); -#endif - _archiveStream = null; - } - } - - return CrcResult; - } - - - - internal Stream GetExtractDecompressor(Stream input2) - { - // get a stream that either decompresses or not. - switch (_CompressionMethod_FromZipFile) - { - case (short)CompressionMethod.None: - return input2; - case (short)CompressionMethod.Deflate: - return new Ionic.Zlib.DeflateStream(input2, Ionic.Zlib.CompressionMode.Decompress, true); -#if BZIP - case (short)CompressionMethod.BZip2: - return new Ionic.BZip2.BZip2InputStream(input2, true); -#endif - } - - return null; - } - - - - internal Stream GetExtractDecryptor(Stream input) - { - Stream input2 = null; - if (_Encryption_FromZipFile == EncryptionAlgorithm.PkzipWeak) - input2 = new ZipCipherStream(input, _zipCrypto_forExtract, CryptoMode.Decrypt); - -#if AESCRYPTO - else if (_Encryption_FromZipFile == EncryptionAlgorithm.WinZipAes128 || - _Encryption_FromZipFile == EncryptionAlgorithm.WinZipAes256) - input2 = new WinZipAesCipherStream(input, _aesCrypto_forExtract, _CompressedFileDataSize, CryptoMode.Decrypt); -#endif - - else - input2 = input; - - return input2; - } - - - - - internal void _SetTimes(string fileOrDirectory, bool isFile) - { -#if SILVERLIGHT - // punt on setting file times -#else - // workitem 8807: - // Because setting the time is not considered to be a fatal error, - // and because other applications can interfere with the setting - // of a time on a directory, we're going to swallow IO exceptions - // in this method. - - try - { - if (_ntfsTimesAreSet) - { -#if NETCF - // workitem 7944: set time should not be a fatal error on CF - int rc = NetCfFile.SetTimes(fileOrDirectory, _Ctime, _Atime, _Mtime); - if ( rc != 0) - { - WriteStatus("Warning: SetTimes failed. entry({0}) file({1}) rc({2})", - FileName, fileOrDirectory, rc); - } -#else - if (isFile) - { - // It's possible that the extract was cancelled, in which case, - // the file does not exist. - if (File.Exists(fileOrDirectory)) - { - File.SetCreationTimeUtc(fileOrDirectory, _Ctime); - File.SetLastAccessTimeUtc(fileOrDirectory, _Atime); - File.SetLastWriteTimeUtc(fileOrDirectory, _Mtime); - } - } - else - { - // It's possible that the extract was cancelled, in which case, - // the directory does not exist. - if (Directory.Exists(fileOrDirectory)) - { - Directory.SetCreationTimeUtc(fileOrDirectory, _Ctime); - Directory.SetLastAccessTimeUtc(fileOrDirectory, _Atime); - Directory.SetLastWriteTimeUtc(fileOrDirectory, _Mtime); - } - } -#endif - } - else - { - // workitem 6191 - DateTime AdjustedLastModified = Ionic.Zip.SharedUtilities.AdjustTime_Reverse(LastModified); - -#if NETCF - int rc = NetCfFile.SetLastWriteTime(fileOrDirectory, AdjustedLastModified); - - if ( rc != 0) - { - WriteStatus("Warning: SetLastWriteTime failed. entry({0}) file({1}) rc({2})", - FileName, fileOrDirectory, rc); - } -#else - if (isFile) - File.SetLastWriteTime(fileOrDirectory, AdjustedLastModified); - else - Directory.SetLastWriteTime(fileOrDirectory, AdjustedLastModified); -#endif - } - } - catch (System.IO.IOException ioexc1) - { - WriteStatus("failed to set time on {0}: {1}", fileOrDirectory, ioexc1.Message); - } -#endif - } - - - #region Support methods - - - // workitem 7968 - private string UnsupportedAlgorithm - { - get - { - string alg = String.Empty; - switch (_UnsupportedAlgorithmId) - { - case 0: - alg = "--"; - break; - case 0x6601: - alg = "DES"; - break; - case 0x6602: // - RC2 (version needed to extract < 5.2) - alg = "RC2"; - break; - case 0x6603: // - 3DES 168 - alg = "3DES-168"; - break; - case 0x6609: // - 3DES 112 - alg = "3DES-112"; - break; - case 0x660E: // - AES 128 - alg = "PKWare AES128"; - break; - case 0x660F: // - AES 192 - alg = "PKWare AES192"; - break; - case 0x6610: // - AES 256 - alg = "PKWare AES256"; - break; - case 0x6702: // - RC2 (version needed to extract >= 5.2) - alg = "RC2"; - break; - case 0x6720: // - Blowfish - alg = "Blowfish"; - break; - case 0x6721: // - Twofish - alg = "Twofish"; - break; - case 0x6801: // - RC4 - alg = "RC4"; - break; - case 0xFFFF: // - Unknown algorithm - default: - alg = String.Format("Unknown (0x{0:X4})", _UnsupportedAlgorithmId); - break; - } - return alg; - } - } - - // workitem 7968 - private string UnsupportedCompressionMethod - { - get - { - string meth = String.Empty; - switch ((int)_CompressionMethod) - { - case 0: - meth = "Store"; - break; - case 1: - meth = "Shrink"; - break; - case 8: - meth = "DEFLATE"; - break; - case 9: - meth = "Deflate64"; - break; - case 12: - meth = "BZIP2"; // only if BZIP not compiled in - break; - case 14: - meth = "LZMA"; - break; - case 19: - meth = "LZ77"; - break; - case 98: - meth = "PPMd"; - break; - default: - meth = String.Format("Unknown (0x{0:X4})", _CompressionMethod); - break; - } - return meth; - } - } - - - internal void ValidateEncryption() - { - if (Encryption != EncryptionAlgorithm.PkzipWeak && -#if AESCRYPTO - Encryption != EncryptionAlgorithm.WinZipAes128 && - Encryption != EncryptionAlgorithm.WinZipAes256 && -#endif - Encryption != EncryptionAlgorithm.None) - { - // workitem 7968 - if (_UnsupportedAlgorithmId != 0) - throw new ZipException(String.Format("Cannot extract: Entry {0} is encrypted with an algorithm not supported by DotNetZip: {1}", - FileName, UnsupportedAlgorithm)); - else - throw new ZipException(String.Format("Cannot extract: Entry {0} uses an unsupported encryption algorithm ({1:X2})", - FileName, (int)Encryption)); - } - } - - - private void ValidateCompression() - { - if ((_CompressionMethod_FromZipFile != (short)CompressionMethod.None) && - (_CompressionMethod_FromZipFile != (short)CompressionMethod.Deflate) -#if BZIP - && (_CompressionMethod_FromZipFile != (short)CompressionMethod.BZip2) -#endif - ) - throw new ZipException(String.Format("Entry {0} uses an unsupported compression method (0x{1:X2}, {2})", - FileName, _CompressionMethod_FromZipFile, UnsupportedCompressionMethod)); - } - - - private void SetupCryptoForExtract(string password) - { - //if (password == null) return; - if (_Encryption_FromZipFile == EncryptionAlgorithm.None) return; - - if (_Encryption_FromZipFile == EncryptionAlgorithm.PkzipWeak) - { - if (password == null) - throw new ZipException("Missing password."); - - this.ArchiveStream.Seek(this.FileDataPosition - 12, SeekOrigin.Begin); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream); - _zipCrypto_forExtract = ZipCrypto.ForRead(password, this); - } - -#if AESCRYPTO - else if (_Encryption_FromZipFile == EncryptionAlgorithm.WinZipAes128 || - _Encryption_FromZipFile == EncryptionAlgorithm.WinZipAes256) - { - if (password == null) - throw new ZipException("Missing password."); - - // If we already have a WinZipAesCrypto object in place, use it. - // It can be set up in the ReadDirEntry(), or during a previous Extract. - if (_aesCrypto_forExtract != null) - { - _aesCrypto_forExtract.Password = password; - } - else - { - int sizeOfSaltAndPv = GetLengthOfCryptoHeaderBytes(_Encryption_FromZipFile); - this.ArchiveStream.Seek(this.FileDataPosition - sizeOfSaltAndPv, SeekOrigin.Begin); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream); - int keystrength = GetKeyStrengthInBits(_Encryption_FromZipFile); - _aesCrypto_forExtract = WinZipAesCrypto.ReadFromStream(password, keystrength, this.ArchiveStream); - } - } -#endif - } - - - - /// - /// Validates that the args are consistent. - /// - /// - /// Only one of {baseDir, outStream} can be non-null. - /// If baseDir is non-null, then the outputFile is created. - /// - private bool ValidateOutput(string basedir, Stream outstream, out string outFileName) - { - if (basedir != null) - { - // Sometimes the name on the entry starts with a slash. - // Rather than unpack to the root of the volume, we're going to - // drop the slash and unpack to the specified base directory. - string f = this.FileName.Replace("\\","/"); - - // workitem 11772: remove drive letter with separator - if (f.IndexOf(':') == 1) - f= f.Substring(2); - - if (f.StartsWith("/")) - f= f.Substring(1); - - // String.Contains is not available on .NET CF 2.0 - - if (_container.ZipFile.FlattenFoldersOnExtract) - outFileName = Path.Combine(basedir, - (f.IndexOf('/') != -1) ? Path.GetFileName(f) : f); - else - outFileName = Path.Combine(basedir, f); - - // workitem 10639 - outFileName = outFileName.Replace("/","\\"); - - // check if it is a directory - if ((IsDirectory) || (FileName.EndsWith("/"))) - { - if (!Directory.Exists(outFileName)) - { - Directory.CreateDirectory(outFileName); - _SetTimes(outFileName, false); - } - else - { - // the dir exists, maybe we want to overwrite times. - if (ExtractExistingFile == ExtractExistingFileAction.OverwriteSilently) - _SetTimes(outFileName, false); - } - return true; // true == all done, caller will return - } - return false; // false == work to do by caller. - } - - if (outstream != null) - { - outFileName = null; - if ((IsDirectory) || (FileName.EndsWith("/"))) - { - // extract a directory to streamwriter? nothing to do! - return true; // true == all done! caller can return - } - return false; - } - - throw new ArgumentNullException("outstream"); - } - - - #endregion - - } -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntry.Read.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntry.Read.cs deleted file mode 100644 index 7a53356d..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntry.Read.cs +++ /dev/null @@ -1,798 +0,0 @@ -// ZipEntry.Read.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-09 21:31:28> -// -// ------------------------------------------------------------------ -// -// This module defines logic for Reading the ZipEntry from a -// zip file. -// -// ------------------------------------------------------------------ - - -using System; -using System.IO; - -namespace Ionic.Zip -{ - public partial class ZipEntry - { - private int _readExtraDepth; - private void ReadExtraField() - { - _readExtraDepth++; - // workitem 8098: ok (restore) - long posn = this.ArchiveStream.Position; - this.ArchiveStream.Seek(this._RelativeOffsetOfLocalHeader, SeekOrigin.Begin); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream); - - byte[] block = new byte[30]; - this.ArchiveStream.Read(block, 0, block.Length); - int i = 26; - Int16 filenameLength = (short)(block[i++] + block[i++] * 256); - Int16 extraFieldLength = (short)(block[i++] + block[i++] * 256); - - // workitem 8098: ok (relative) - this.ArchiveStream.Seek(filenameLength, SeekOrigin.Current); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream); - - ProcessExtraField(this.ArchiveStream, extraFieldLength); - - // workitem 8098: ok (restore) - this.ArchiveStream.Seek(posn, SeekOrigin.Begin); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream); - _readExtraDepth--; - } - - - private static bool ReadHeader(ZipEntry ze, System.Text.Encoding defaultEncoding) - { - int bytesRead = 0; - - // change for workitem 8098 - ze._RelativeOffsetOfLocalHeader = ze.ArchiveStream.Position; - - int signature = Ionic.Zip.SharedUtilities.ReadEntrySignature(ze.ArchiveStream); - bytesRead += 4; - - // Return false if this is not a local file header signature. - if (ZipEntry.IsNotValidSig(signature)) - { - // Getting "not a ZipEntry signature" is not always wrong or an error. - // This will happen after the last entry in a zipfile. In that case, we - // expect to read : - // a ZipDirEntry signature (if a non-empty zip file) or - // a ZipConstants.EndOfCentralDirectorySignature. - // - // Anything else is a surprise. - - ze.ArchiveStream.Seek(-4, SeekOrigin.Current); // unread the signature - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(ze.ArchiveStream); - if (ZipEntry.IsNotValidZipDirEntrySig(signature) && (signature != ZipConstants.EndOfCentralDirectorySignature)) - { - throw new BadReadException(String.Format(" Bad signature (0x{0:X8}) at position 0x{1:X8}", signature, ze.ArchiveStream.Position)); - } - return false; - } - - byte[] block = new byte[26]; - int n = ze.ArchiveStream.Read(block, 0, block.Length); - if (n != block.Length) return false; - bytesRead += n; - - int i = 0; - ze._VersionNeeded = (Int16)(block[i++] + block[i++] * 256); - ze._BitField = (Int16)(block[i++] + block[i++] * 256); - ze._CompressionMethod_FromZipFile = ze._CompressionMethod = (Int16)(block[i++] + block[i++] * 256); - ze._TimeBlob = block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256; - // transform the time data into something usable (a DateTime) - ze._LastModified = Ionic.Zip.SharedUtilities.PackedToDateTime(ze._TimeBlob); - ze._timestamp |= ZipEntryTimestamp.DOS; - - if ((ze._BitField & 0x01) == 0x01) - { - ze._Encryption_FromZipFile = ze._Encryption = EncryptionAlgorithm.PkzipWeak; // this *may* change after processing the Extra field - ze._sourceIsEncrypted = true; - } - - // NB: if ((ze._BitField & 0x0008) != 0x0008), then the Compressed, uncompressed and - // CRC values are not true values; the true values will follow the entry data. - // But, regardless of the status of bit 3 in the bitfield, the slots for - // the three amigos may contain marker values for ZIP64. So we must read them. - { - ze._Crc32 = (Int32)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256); - ze._CompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256); - ze._UncompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256); - - if ((uint)ze._CompressedSize == 0xFFFFFFFF || - (uint)ze._UncompressedSize == 0xFFFFFFFF) - - ze._InputUsesZip64 = true; - } - - Int16 filenameLength = (short)(block[i++] + block[i++] * 256); - Int16 extraFieldLength = (short)(block[i++] + block[i++] * 256); - - block = new byte[filenameLength]; - n = ze.ArchiveStream.Read(block, 0, block.Length); - bytesRead += n; - - // if the UTF8 bit is set for this entry, override the - // encoding the application requested. - - if ((ze._BitField & 0x0800) == 0x0800) - { - // workitem 12744 - ze.AlternateEncoding = System.Text.Encoding.UTF8; - ze.AlternateEncodingUsage = ZipOption.Always; - } - - // need to use this form of GetString() for .NET CF - ze._FileNameInArchive = ze.AlternateEncoding.GetString(block, 0, block.Length); - - // workitem 6898 - if (ze._FileNameInArchive.EndsWith("/")) ze.MarkAsDirectory(); - - bytesRead += ze.ProcessExtraField(ze.ArchiveStream, extraFieldLength); - - ze._LengthOfTrailer = 0; - - // workitem 6607 - don't read for directories - // actually get the compressed size and CRC if necessary - if (!ze._FileNameInArchive.EndsWith("/") && (ze._BitField & 0x0008) == 0x0008) - { - // This descriptor exists only if bit 3 of the general - // purpose bit flag is set (see below). It is byte aligned - // and immediately follows the last byte of compressed data, - // as well as any encryption trailer, as with AES. - // This descriptor is used only when it was not possible to - // seek in the output .ZIP file, e.g., when the output .ZIP file - // was standard output or a non-seekable device. For ZIP64(tm) format - // archives, the compressed and uncompressed sizes are 8 bytes each. - - // workitem 8098: ok (restore) - long posn = ze.ArchiveStream.Position; - - // Here, we're going to loop until we find a ZipEntryDataDescriptorSignature and - // a consistent data record after that. To be consistent, the data record must - // indicate the length of the entry data. - bool wantMore = true; - long SizeOfDataRead = 0; - int tries = 0; - while (wantMore) - { - tries++; - // We call the FindSignature shared routine to find the specified signature - // in the already-opened zip archive, starting from the current cursor - // position in that filestream. If we cannot find the signature, then the - // routine returns -1, and the ReadHeader() method returns false, - // indicating we cannot read a legal entry header. If we have found it, - // then the FindSignature() method returns the number of bytes in the - // stream we had to seek forward, to find the sig. We need this to - // determine if the zip entry is valid, later. - - if (ze._container.ZipFile != null) - ze._container.ZipFile.OnReadBytes(ze); - - long d = Ionic.Zip.SharedUtilities.FindSignature(ze.ArchiveStream, ZipConstants.ZipEntryDataDescriptorSignature); - if (d == -1) return false; - - // total size of data read (through all loops of this). - SizeOfDataRead += d; - - if (ze._InputUsesZip64) - { - // read 1x 4-byte (CRC) and 2x 8-bytes (Compressed Size, Uncompressed Size) - block = new byte[20]; - n = ze.ArchiveStream.Read(block, 0, block.Length); - if (n != 20) return false; - - // do not increment bytesRead - it is for entry header only. - // the data we have just read is a footer (falls after the file data) - //bytesRead += n; - - i = 0; - ze._Crc32 = (Int32)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256); - ze._CompressedSize = BitConverter.ToInt64(block, i); - i += 8; - ze._UncompressedSize = BitConverter.ToInt64(block, i); - i += 8; - - ze._LengthOfTrailer += 24; // bytes including sig, CRC, Comp and Uncomp sizes - } - else - { - // read 3x 4-byte fields (CRC, Compressed Size, Uncompressed Size) - block = new byte[12]; - n = ze.ArchiveStream.Read(block, 0, block.Length); - if (n != 12) return false; - - // do not increment bytesRead - it is for entry header only. - // the data we have just read is a footer (falls after the file data) - //bytesRead += n; - - i = 0; - ze._Crc32 = (Int32)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256); - ze._CompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256); - ze._UncompressedSize = (uint)(block[i++] + block[i++] * 256 + block[i++] * 256 * 256 + block[i++] * 256 * 256 * 256); - - ze._LengthOfTrailer += 16; // bytes including sig, CRC, Comp and Uncomp sizes - - } - - wantMore = (SizeOfDataRead != ze._CompressedSize); - - if (wantMore) - { - // Seek back to un-read the last 12 bytes - maybe THEY contain - // the ZipEntryDataDescriptorSignature. - // (12 bytes for the CRC, Comp and Uncomp size.) - ze.ArchiveStream.Seek(-12, SeekOrigin.Current); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(ze.ArchiveStream); - - // Adjust the size to account for the false signature read in - // FindSignature(). - SizeOfDataRead += 4; - } - } - - // seek back to previous position, to prepare to read file data - // workitem 8098: ok (restore) - ze.ArchiveStream.Seek(posn, SeekOrigin.Begin); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(ze.ArchiveStream); - } - - ze._CompressedFileDataSize = ze._CompressedSize; - - - // bit 0 set indicates that some kind of encryption is in use - if ((ze._BitField & 0x01) == 0x01) - { -#if AESCRYPTO - if (ze.Encryption == EncryptionAlgorithm.WinZipAes128 || - ze.Encryption == EncryptionAlgorithm.WinZipAes256) - { - int bits = ZipEntry.GetKeyStrengthInBits(ze._Encryption_FromZipFile); - // read in the WinZip AES metadata: salt + PV. 18 bytes for AES256. 10 bytes for AES128. - ze._aesCrypto_forExtract = WinZipAesCrypto.ReadFromStream(null, bits, ze.ArchiveStream); - bytesRead += ze._aesCrypto_forExtract.SizeOfEncryptionMetadata - 10; // MAC (follows crypto bytes) - // according to WinZip, the CompressedSize includes the AES Crypto framing data. - ze._CompressedFileDataSize -= ze._aesCrypto_forExtract.SizeOfEncryptionMetadata; - ze._LengthOfTrailer += 10; // MAC - } - else -#endif - { - // read in the header data for "weak" encryption - ze._WeakEncryptionHeader = new byte[12]; - bytesRead += ZipEntry.ReadWeakEncryptionHeader(ze._archiveStream, ze._WeakEncryptionHeader); - // decrease the filedata size by 12 bytes - ze._CompressedFileDataSize -= 12; - } - } - - // Remember the size of the blob for this entry. - // We also have the starting position in the stream for this entry. - ze._LengthOfHeader = bytesRead; - ze._TotalEntrySize = ze._LengthOfHeader + ze._CompressedFileDataSize + ze._LengthOfTrailer; - - - // We've read in the regular entry header, the extra field, and any - // encryption header. The pointer in the file is now at the start of the - // filedata, which is potentially compressed and encrypted. Just ahead in - // the file, there are _CompressedFileDataSize bytes of data, followed by - // potentially a non-zero length trailer, consisting of optionally, some - // encryption stuff (10 byte MAC for AES), and the bit-3 trailer (16 or 24 - // bytes). - - return true; - } - - - - internal static int ReadWeakEncryptionHeader(Stream s, byte[] buffer) - { - // PKZIP encrypts the compressed data stream. Encrypted files must - // be decrypted before they can be extracted. - - // Each PKZIP-encrypted file has an extra 12 bytes stored at the start of the data - // area defining the encryption header for that file. The encryption header is - // originally set to random values, and then itself encrypted, using three, 32-bit - // keys. The key values are initialized using the supplied encryption password. - // After each byte is encrypted, the keys are then updated using pseudo-random - // number generation techniques in combination with the same CRC-32 algorithm used - // in PKZIP and implemented in the CRC32.cs module in this project. - - // read the 12-byte encryption header - int additionalBytesRead = s.Read(buffer, 0, 12); - if (additionalBytesRead != 12) - throw new ZipException(String.Format("Unexpected end of data at position 0x{0:X8}", s.Position)); - - return additionalBytesRead; - } - - - - private static bool IsNotValidSig(int signature) - { - return (signature != ZipConstants.ZipEntrySignature); - } - - - /// - /// Reads one ZipEntry from the given stream. The content for - /// the entry does not get decompressed or decrypted. This method - /// basically reads metadata, and seeks. - /// - /// the ZipContainer this entry belongs to. - /// - /// true of this is the first entry being read from the stream. - /// - /// the ZipEntry read from the stream. - internal static ZipEntry ReadEntry(ZipContainer zc, bool first) - { - ZipFile zf = zc.ZipFile; - Stream s = zc.ReadStream; - System.Text.Encoding defaultEncoding = zc.AlternateEncoding; - ZipEntry entry = new ZipEntry(); - entry._Source = ZipEntrySource.ZipFile; - entry._container = zc; - entry._archiveStream = s; - if (zf != null) - zf.OnReadEntry(true, null); - - if (first) HandlePK00Prefix(s); - - // Read entry header, including any encryption header - if (!ReadHeader(entry, defaultEncoding)) return null; - - // Store the position in the stream for this entry - // change for workitem 8098 - entry.__FileDataPosition = entry.ArchiveStream.Position; - - // seek past the data without reading it. We will read on Extract() - s.Seek(entry._CompressedFileDataSize + entry._LengthOfTrailer, SeekOrigin.Current); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(s); - - // ReadHeader moves the file pointer to the end of the entry header, - // as well as any encryption header. - - // CompressedFileDataSize includes: - // the maybe compressed, maybe encrypted file data - // the encryption trailer, if any - // the bit 3 descriptor, if any - - // workitem 5306 - // http://www.codeplex.com/DotNetZip/WorkItem/View.aspx?WorkItemId=5306 - HandleUnexpectedDataDescriptor(entry); - - if (zf != null) - { - zf.OnReadBytes(entry); - zf.OnReadEntry(false, entry); - } - - return entry; - } - - - internal static void HandlePK00Prefix(Stream s) - { - // in some cases, the zip file begins with "PK00". This is a throwback and is rare, - // but we handle it anyway. We do not change behavior based on it. - uint datum = (uint)Ionic.Zip.SharedUtilities.ReadInt(s); - if (datum != ZipConstants.PackedToRemovableMedia) - { - s.Seek(-4, SeekOrigin.Current); // unread the block - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(s); - } - } - - - - private static void HandleUnexpectedDataDescriptor(ZipEntry entry) - { - Stream s = entry.ArchiveStream; - - // In some cases, the "data descriptor" is present, without a signature, even when - // bit 3 of the BitField is NOT SET. This is the CRC, followed - // by the compressed length and the uncompressed length (4 bytes for each - // of those three elements). Need to check that here. - // - uint datum = (uint)Ionic.Zip.SharedUtilities.ReadInt(s); - if (datum == entry._Crc32) - { - int sz = Ionic.Zip.SharedUtilities.ReadInt(s); - if (sz == entry._CompressedSize) - { - sz = Ionic.Zip.SharedUtilities.ReadInt(s); - if (sz == entry._UncompressedSize) - { - // ignore everything and discard it. - } - else - { - s.Seek(-12, SeekOrigin.Current); // unread the three blocks - - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(s); - } - } - else - { - s.Seek(-8, SeekOrigin.Current); // unread the two blocks - - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(s); - } - } - else - { - s.Seek(-4, SeekOrigin.Current); // unread the block - - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(s); - } - } - - - /// - /// Finds a particular segment in the given extra field. - /// This is used when modifying a previously-generated - /// extra field, in particular when removing the AES crypto - /// segment in the extra field. - /// - static internal int FindExtraFieldSegment(byte[] extra, int offx, UInt16 targetHeaderId) - { - int j = offx; - while (j + 3 < extra.Length) - { - UInt16 headerId = (UInt16)(extra[j++] + extra[j++] * 256); - if (headerId == targetHeaderId) return j-2; - - // else advance to next segment - Int16 dataSize = (short)(extra[j++] + extra[j++] * 256); - j+= dataSize; - } - - return -1; - } - - - /// - /// At current cursor position in the stream, read the extra - /// field, and set the properties on the ZipEntry instance - /// appropriately. This can be called when processing the - /// Extra field in the Central Directory, or in the local - /// header. - /// - internal int ProcessExtraField(Stream s, Int16 extraFieldLength) - { - int additionalBytesRead = 0; - if (extraFieldLength > 0) - { - byte[] buffer = this._Extra = new byte[extraFieldLength]; - additionalBytesRead = s.Read(buffer, 0, buffer.Length); - long posn = s.Position - additionalBytesRead; - int j = 0; - while (j + 3 < buffer.Length) - { - int start = j; - UInt16 headerId = (UInt16)(buffer[j++] + buffer[j++] * 256); - Int16 dataSize = (short)(buffer[j++] + buffer[j++] * 256); - - switch (headerId) - { - case 0x000a: // NTFS ctime, atime, mtime - j = ProcessExtraFieldWindowsTimes(buffer, j, dataSize, posn); - break; - - case 0x5455: // Unix ctime, atime, mtime - j = ProcessExtraFieldUnixTimes(buffer, j, dataSize, posn); - break; - - case 0x5855: // Info-zip Extra field (outdated) - // This is outdated, so the field is supported on - // read only. - j = ProcessExtraFieldInfoZipTimes(buffer, j, dataSize, posn); - break; - - case 0x7855: // Unix uid/gid - // ignored. DotNetZip does not handle this field. - break; - - case 0x7875: // ?? - // ignored. I could not find documentation on this field, - // though it appears in some zip files. - break; - - case 0x0001: // ZIP64 - j = ProcessExtraFieldZip64(buffer, j, dataSize, posn); - break; - -#if AESCRYPTO - case 0x9901: // WinZip AES encryption is in use. (workitem 6834) - // we will handle this extra field only if compressionmethod is 0x63 - j = ProcessExtraFieldWinZipAes(buffer, j, dataSize, posn); - break; -#endif - case 0x0017: // workitem 7968: handle PKWare Strong encryption header - j = ProcessExtraFieldPkwareStrongEncryption(buffer, j); - break; - } - - // move to the next Header in the extra field - j = start + dataSize + 4; - } - } - return additionalBytesRead; - } - - private int ProcessExtraFieldPkwareStrongEncryption(byte[] Buffer, int j) - { - // Value Size Description - // ----- ---- ----------- - // 0x0017 2 bytes Tag for this "extra" block type - // TSize 2 bytes Size of data that follows - // Format 2 bytes Format definition for this record - // AlgID 2 bytes Encryption algorithm identifier - // Bitlen 2 bytes Bit length of encryption key - // Flags 2 bytes Processing flags - // CertData TSize-8 Certificate decryption extra field data - // (refer to the explanation for CertData - // in the section describing the - // Certificate Processing Method under - // the Strong Encryption Specification) - - j += 2; - _UnsupportedAlgorithmId = (UInt16)(Buffer[j++] + Buffer[j++] * 256); - _Encryption_FromZipFile = _Encryption = EncryptionAlgorithm.Unsupported; - - // DotNetZip doesn't support this algorithm, but we don't need to throw - // here. we might just be reading the archive, which is fine. We'll - // need to throw if Extract() is called. - - return j; - } - - -#if AESCRYPTO - private int ProcessExtraFieldWinZipAes(byte[] buffer, int j, Int16 dataSize, long posn) - { - if (this._CompressionMethod == 0x0063) - { - if ((this._BitField & 0x01) != 0x01) - throw new BadReadException(String.Format(" Inconsistent metadata at position 0x{0:X16}", posn)); - - this._sourceIsEncrypted = true; - - //this._aesCrypto = new WinZipAesCrypto(this); - // see spec at http://www.winzip.com/aes_info.htm - if (dataSize != 7) - throw new BadReadException(String.Format(" Inconsistent size (0x{0:X4}) in WinZip AES field at position 0x{1:X16}", dataSize, posn)); - - this._WinZipAesMethod = BitConverter.ToInt16(buffer, j); - j += 2; - if (this._WinZipAesMethod != 0x01 && this._WinZipAesMethod != 0x02) - throw new BadReadException(String.Format(" Unexpected vendor version number (0x{0:X4}) for WinZip AES metadata at position 0x{1:X16}", - this._WinZipAesMethod, posn)); - - Int16 vendorId = BitConverter.ToInt16(buffer, j); - j += 2; - if (vendorId != 0x4541) - throw new BadReadException(String.Format(" Unexpected vendor ID (0x{0:X4}) for WinZip AES metadata at position 0x{1:X16}", vendorId, posn)); - - int keystrength = (buffer[j] == 1) ? 128 : (buffer[j] == 3) ? 256 : -1; - if (keystrength < 0) - throw new BadReadException(String.Format("Invalid key strength ({0})", keystrength)); - - _Encryption_FromZipFile = this._Encryption = (keystrength == 128) - ? EncryptionAlgorithm.WinZipAes128 - : EncryptionAlgorithm.WinZipAes256; - - j++; - - // set the actual compression method - this._CompressionMethod_FromZipFile = - this._CompressionMethod = BitConverter.ToInt16(buffer, j); - j += 2; // for the next segment of the extra field - } - return j; - } - -#endif - - private delegate T Func(); - - private int ProcessExtraFieldZip64(byte[] buffer, int j, Int16 dataSize, long posn) - { - // The PKWare spec says that any of {UncompressedSize, CompressedSize, - // RelativeOffset} exceeding 0xFFFFFFFF can lead to the ZIP64 header, - // and the ZIP64 header may contain one or more of those. If the - // values are present, they will be found in the prescribed order. - // There may also be a 4-byte "disk start number." - // This means that the DataSize must be 28 bytes or less. - - this._InputUsesZip64 = true; - - // workitem 7941: check datasize before reading. - if (dataSize > 28) - throw new BadReadException(String.Format(" Inconsistent size (0x{0:X4}) for ZIP64 extra field at position 0x{1:X16}", - dataSize, posn)); - int remainingData = dataSize; - - var slurp = new Func( () => { - if (remainingData < 8) - throw new BadReadException(String.Format(" Missing data for ZIP64 extra field, position 0x{0:X16}", posn)); - var x = BitConverter.ToInt64(buffer, j); - j+= 8; - remainingData -= 8; - return x; - }); - - if (this._UncompressedSize == 0xFFFFFFFF) - this._UncompressedSize = slurp(); - - if (this._CompressedSize == 0xFFFFFFFF) - this._CompressedSize = slurp(); - - if (this._RelativeOffsetOfLocalHeader == 0xFFFFFFFF) - this._RelativeOffsetOfLocalHeader = slurp(); - - // Ignore anything else. Potentially there are 4 more bytes for the - // disk start number. DotNetZip currently doesn't handle multi-disk - // archives. - return j; - } - - - private int ProcessExtraFieldInfoZipTimes(byte[] buffer, int j, Int16 dataSize, long posn) - { - if (dataSize != 12 && dataSize != 8) - throw new BadReadException(String.Format(" Unexpected size (0x{0:X4}) for InfoZip v1 extra field at position 0x{1:X16}", dataSize, posn)); - - Int32 timet = BitConverter.ToInt32(buffer, j); - this._Mtime = _unixEpoch.AddSeconds(timet); - j += 4; - - timet = BitConverter.ToInt32(buffer, j); - this._Atime = _unixEpoch.AddSeconds(timet); - j += 4; - - this._Ctime = DateTime.UtcNow; - - _ntfsTimesAreSet = true; - _timestamp |= ZipEntryTimestamp.InfoZip1; return j; - } - - - - private int ProcessExtraFieldUnixTimes(byte[] buffer, int j, Int16 dataSize, long posn) - { - // The Unix filetimes are 32-bit unsigned integers, - // storing seconds since Unix epoch. - - if (dataSize != 13 && dataSize != 9 && dataSize != 5) - throw new BadReadException(String.Format(" Unexpected size (0x{0:X4}) for Extended Timestamp extra field at position 0x{1:X16}", dataSize, posn)); - - int remainingData = dataSize; - - var slurp = new Func( () => { - Int32 timet = BitConverter.ToInt32(buffer, j); - j += 4; - remainingData -= 4; - return _unixEpoch.AddSeconds(timet); - }); - - if (dataSize == 13 || _readExtraDepth > 0) - { - byte flag = buffer[j++]; - remainingData--; - - if ((flag & 0x0001) != 0 && remainingData >= 4) - this._Mtime = slurp(); - - this._Atime = ((flag & 0x0002) != 0 && remainingData >= 4) - ? slurp() - : DateTime.UtcNow; - - this._Ctime = ((flag & 0x0004) != 0 && remainingData >= 4) - ? slurp() - :DateTime.UtcNow; - - _timestamp |= ZipEntryTimestamp.Unix; - _ntfsTimesAreSet = true; - _emitUnixTimes = true; - } - else - ReadExtraField(); // will recurse - - return j; - } - - - private int ProcessExtraFieldWindowsTimes(byte[] buffer, int j, Int16 dataSize, long posn) - { - // The NTFS filetimes are 64-bit unsigned integers, stored in Intel - // (least significant byte first) byte order. They are expressed as the - // number of 1.0E-07 seconds (1/10th microseconds!) past WinNT "epoch", - // which is "01-Jan-1601 00:00:00 UTC". - // - // HeaderId 2 bytes 0x000a == NTFS stuff - // Datasize 2 bytes ?? (usually 32) - // reserved 4 bytes ?? - // timetag 2 bytes 0x0001 == time - // size 2 bytes 24 == 8 bytes each for ctime, mtime, atime - // mtime 8 bytes win32 ticks since win32epoch - // atime 8 bytes win32 ticks since win32epoch - // ctime 8 bytes win32 ticks since win32epoch - - if (dataSize != 32) - throw new BadReadException(String.Format(" Unexpected size (0x{0:X4}) for NTFS times extra field at position 0x{1:X16}", dataSize, posn)); - - j += 4; // reserved - Int16 timetag = (Int16)(buffer[j] + buffer[j + 1] * 256); - Int16 addlsize = (Int16)(buffer[j + 2] + buffer[j + 3] * 256); - j += 4; // tag and size - - if (timetag == 0x0001 && addlsize == 24) - { - Int64 z = BitConverter.ToInt64(buffer, j); - this._Mtime = DateTime.FromFileTimeUtc(z); - j += 8; - - // At this point the library *could* set the LastModified value - // to coincide with the Mtime value. In theory, they refer to - // the same property of the file, and should be the same anyway, - // allowing for differences in precision. But they are - // independent quantities in the zip archive, and this library - // will keep them separate in the object model. There is no ill - // effect from this, because as files are extracted, the - // higher-precision value (Mtime) is used if it is present. - // Apps may wish to compare the Mtime versus LastModified - // values, but any difference when both are present is not - // germaine to the correctness of the library. but note: when - // explicitly setting either value, both are set. See the setter - // for LastModified or the SetNtfsTimes() method. - - z = BitConverter.ToInt64(buffer, j); - this._Atime = DateTime.FromFileTimeUtc(z); - j += 8; - - z = BitConverter.ToInt64(buffer, j); - this._Ctime = DateTime.FromFileTimeUtc(z); - j += 8; - - _ntfsTimesAreSet = true; - _timestamp |= ZipEntryTimestamp.Windows; - _emitNtfsTimes = true; - } - return j; - } - - - } -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntry.Write.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntry.Write.cs deleted file mode 100644 index b4e87f6e..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntry.Write.cs +++ /dev/null @@ -1,2582 +0,0 @@ -//#define Trace - -// ZipEntry.Write.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: <2011-July-30 14:55:47> -// -// ------------------------------------------------------------------ -// -// This module defines logic for writing (saving) the ZipEntry into a -// zip file. -// -// ------------------------------------------------------------------ - - -using System; -using System.IO; -using RE = System.Text.RegularExpressions; - -namespace Ionic.Zip -{ - public partial class ZipEntry - { - internal void WriteCentralDirectoryEntry(Stream s) - { - byte[] bytes = new byte[4096]; - int i = 0; - // signature - bytes[i++] = (byte)(ZipConstants.ZipDirEntrySignature & 0x000000FF); - bytes[i++] = (byte)((ZipConstants.ZipDirEntrySignature & 0x0000FF00) >> 8); - bytes[i++] = (byte)((ZipConstants.ZipDirEntrySignature & 0x00FF0000) >> 16); - bytes[i++] = (byte)((ZipConstants.ZipDirEntrySignature & 0xFF000000) >> 24); - - // Version Made By - // workitem 7071 - // We must not overwrite the VersionMadeBy field when writing out a zip - // archive. The VersionMadeBy tells the zip reader the meaning of the - // File attributes. Overwriting the VersionMadeBy will result in - // inconsistent metadata. Consider the scenario where the application - // opens and reads a zip file that had been created on Linux. Then the - // app adds one file to the Zip archive, and saves it. The file - // attributes for all the entries added on Linux will be significant for - // Linux. Therefore the VersionMadeBy for those entries must not be - // changed. Only the entries that are actually created on Windows NTFS - // should get the VersionMadeBy indicating Windows/NTFS. - bytes[i++] = (byte)(_VersionMadeBy & 0x00FF); - bytes[i++] = (byte)((_VersionMadeBy & 0xFF00) >> 8); - - // Apparently we want to duplicate the extra field here; we cannot - // simply zero it out and assume tools and apps will use the right one. - - ////Int16 extraFieldLengthSave = (short)(_EntryHeader[28] + _EntryHeader[29] * 256); - ////_EntryHeader[28] = 0; - ////_EntryHeader[29] = 0; - - // Version Needed, Bitfield, compression method, lastmod, - // crc, compressed and uncompressed sizes, filename length and extra field length. - // These are all present in the local file header, but they may be zero values there. - // So we cannot just copy them. - - // workitem 11969: Version Needed To Extract in central directory must be - // the same as the local entry or MS .NET System.IO.Zip fails read. - Int16 vNeeded = (Int16)(VersionNeeded != 0 ? VersionNeeded : 20); - // workitem 12964 - if (_OutputUsesZip64==null) - { - // a zipentry in a zipoutputstream, with zero bytes written - _OutputUsesZip64 = new Nullable(_container.Zip64 == Zip64Option.Always); - } - - Int16 versionNeededToExtract = (Int16)(_OutputUsesZip64.Value ? 45 : vNeeded); -#if BZIP - if (this.CompressionMethod == Ionic.Zip.CompressionMethod.BZip2) - versionNeededToExtract = 46; -#endif - - bytes[i++] = (byte)(versionNeededToExtract & 0x00FF); - bytes[i++] = (byte)((versionNeededToExtract & 0xFF00) >> 8); - - bytes[i++] = (byte)(_BitField & 0x00FF); - bytes[i++] = (byte)((_BitField & 0xFF00) >> 8); - - bytes[i++] = (byte)(_CompressionMethod & 0x00FF); - bytes[i++] = (byte)((_CompressionMethod & 0xFF00) >> 8); - -#if AESCRYPTO - if (Encryption == EncryptionAlgorithm.WinZipAes128 || - Encryption == EncryptionAlgorithm.WinZipAes256) - { - i -= 2; - bytes[i++] = 0x63; - bytes[i++] = 0; - } -#endif - - bytes[i++] = (byte)(_TimeBlob & 0x000000FF); - bytes[i++] = (byte)((_TimeBlob & 0x0000FF00) >> 8); - bytes[i++] = (byte)((_TimeBlob & 0x00FF0000) >> 16); - bytes[i++] = (byte)((_TimeBlob & 0xFF000000) >> 24); - bytes[i++] = (byte)(_Crc32 & 0x000000FF); - bytes[i++] = (byte)((_Crc32 & 0x0000FF00) >> 8); - bytes[i++] = (byte)((_Crc32 & 0x00FF0000) >> 16); - bytes[i++] = (byte)((_Crc32 & 0xFF000000) >> 24); - - int j = 0; - if (_OutputUsesZip64.Value) - { - // CompressedSize (Int32) and UncompressedSize - all 0xFF - for (j = 0; j < 8; j++) - bytes[i++] = 0xFF; - } - else - { - bytes[i++] = (byte)(_CompressedSize & 0x000000FF); - bytes[i++] = (byte)((_CompressedSize & 0x0000FF00) >> 8); - bytes[i++] = (byte)((_CompressedSize & 0x00FF0000) >> 16); - bytes[i++] = (byte)((_CompressedSize & 0xFF000000) >> 24); - - bytes[i++] = (byte)(_UncompressedSize & 0x000000FF); - bytes[i++] = (byte)((_UncompressedSize & 0x0000FF00) >> 8); - bytes[i++] = (byte)((_UncompressedSize & 0x00FF0000) >> 16); - bytes[i++] = (byte)((_UncompressedSize & 0xFF000000) >> 24); - } - - byte[] fileNameBytes = GetEncodedFileNameBytes(); - Int16 filenameLength = (Int16)fileNameBytes.Length; - bytes[i++] = (byte)(filenameLength & 0x00FF); - bytes[i++] = (byte)((filenameLength & 0xFF00) >> 8); - - // do this again because now we have real data - _presumeZip64 = _OutputUsesZip64.Value; - - // workitem 11131 - // - // cannot generate the extra field again, here's why: In the case of a - // zero-byte entry, which uses encryption, DotNetZip will "remove" the - // encryption from the entry. It does this in PostProcessOutput; it - // modifies the entry header, and rewrites it, resetting the Bitfield - // (one bit indicates encryption), and potentially resetting the - // compression method - for AES the Compression method is 0x63, and it - // would get reset to zero (no compression). It then calls SetLength() - // to truncate the stream to remove the encryption header (12 bytes for - // AES256). But, it leaves the previously-generated "Extra Field" - // metadata (11 bytes) for AES in the entry header. This extra field - // data is now "orphaned" - it refers to AES encryption when in fact no - // AES encryption is used. But no problem, the PKWARE spec says that - // unrecognized extra fields can just be ignored. ok. After "removal" - // of AES encryption, the length of the Extra Field can remains the - // same; it's just that there will be 11 bytes in there that previously - // pertained to AES which are now unused. Even the field code is still - // there, but it will be unused by readers, as the encryption bit is not - // set. - // - // Re-calculating the Extra field now would produce a block that is 11 - // bytes shorter, and that mismatch - between the extra field in the - // local header and the extra field in the Central Directory - would - // cause problems. (where? why? what problems?) So we can't do - // that. It's all good though, because though the content may have - // changed, the length definitely has not. Also, the _EntryHeader - // contains the "updated" extra field (after PostProcessOutput) at - // offset (30 + filenameLength). - - _Extra = ConstructExtraField(true); - - Int16 extraFieldLength = (Int16)((_Extra == null) ? 0 : _Extra.Length); - bytes[i++] = (byte)(extraFieldLength & 0x00FF); - bytes[i++] = (byte)((extraFieldLength & 0xFF00) >> 8); - - // File (entry) Comment Length - // the _CommentBytes private field was set during WriteHeader() - int commentLength = (_CommentBytes == null) ? 0 : _CommentBytes.Length; - - // the size of our buffer defines the max length of the comment we can write - if (commentLength + i > bytes.Length) commentLength = bytes.Length - i; - bytes[i++] = (byte)(commentLength & 0x00FF); - bytes[i++] = (byte)((commentLength & 0xFF00) >> 8); - - // Disk number start - bool segmented = (this._container.ZipFile != null) && - (this._container.ZipFile.MaxOutputSegmentSize != 0); - if (segmented) // workitem 13915 - { - // Emit nonzero disknumber only if saving segmented archive. - bytes[i++] = (byte)(_diskNumber & 0x00FF); - bytes[i++] = (byte)((_diskNumber & 0xFF00) >> 8); - } - else - { - // If reading a segmneted archive and saving to a regular archive, - // ZipEntry._diskNumber will be non-zero but it should be saved as - // zero. - bytes[i++] = 0; - bytes[i++] = 0; - } - - // internal file attrs - // workitem 7801 - bytes[i++] = (byte)((_IsText) ? 1 : 0); // lo bit: filetype hint. 0=bin, 1=txt. - bytes[i++] = 0; - - // external file attrs - // workitem 7071 - bytes[i++] = (byte)(_ExternalFileAttrs & 0x000000FF); - bytes[i++] = (byte)((_ExternalFileAttrs & 0x0000FF00) >> 8); - bytes[i++] = (byte)((_ExternalFileAttrs & 0x00FF0000) >> 16); - bytes[i++] = (byte)((_ExternalFileAttrs & 0xFF000000) >> 24); - - // workitem 11131 - // relative offset of local header. - // - // If necessary to go to 64-bit value, then emit 0xFFFFFFFF, - // else write out the value. - // - // Even if zip64 is required for other reasons - number of the entry - // > 65534, or uncompressed size of the entry > MAX_INT32, the ROLH - // need not be stored in a 64-bit field . - if (_RelativeOffsetOfLocalHeader > 0xFFFFFFFFL) // _OutputUsesZip64.Value - { - bytes[i++] = 0xFF; - bytes[i++] = 0xFF; - bytes[i++] = 0xFF; - bytes[i++] = 0xFF; - } - else - { - bytes[i++] = (byte)(_RelativeOffsetOfLocalHeader & 0x000000FF); - bytes[i++] = (byte)((_RelativeOffsetOfLocalHeader & 0x0000FF00) >> 8); - bytes[i++] = (byte)((_RelativeOffsetOfLocalHeader & 0x00FF0000) >> 16); - bytes[i++] = (byte)((_RelativeOffsetOfLocalHeader & 0xFF000000) >> 24); - } - - // actual filename - Buffer.BlockCopy(fileNameBytes, 0, bytes, i, filenameLength); - i += filenameLength; - - // "Extra field" - if (_Extra != null) - { - // workitem 11131 - // - // copy from EntryHeader if available - it may have been updated. - // if not, copy from Extra. This would be unnecessary if I just - // updated the Extra field when updating EntryHeader, in - // PostProcessOutput. - - //?? I don't understand why I wouldn't want to just use - // the recalculated Extra field. ?? - - // byte[] h = _EntryHeader ?? _Extra; - // int offx = (h == _EntryHeader) ? 30 + filenameLength : 0; - // Buffer.BlockCopy(h, offx, bytes, i, extraFieldLength); - // i += extraFieldLength; - - byte[] h = _Extra; - int offx = 0; - Buffer.BlockCopy(h, offx, bytes, i, extraFieldLength); - i += extraFieldLength; - } - - // file (entry) comment - if (commentLength != 0) - { - // now actually write the comment itself into the byte buffer - Buffer.BlockCopy(_CommentBytes, 0, bytes, i, commentLength); - // for (j = 0; (j < commentLength) && (i + j < bytes.Length); j++) - // bytes[i + j] = _CommentBytes[j]; - i += commentLength; - } - - s.Write(bytes, 0, i); - } - - -#if INFOZIP_UTF8 - static private bool FileNameIsUtf8(char[] FileNameChars) - { - bool isUTF8 = false; - bool isUnicode = false; - for (int j = 0; j < FileNameChars.Length; j++) - { - byte[] b = System.BitConverter.GetBytes(FileNameChars[j]); - isUnicode |= (b.Length != 2); - isUnicode |= (b[1] != 0); - isUTF8 |= ((b[0] & 0x80) != 0); - } - - return isUTF8; - } -#endif - - - private byte[] ConstructExtraField(bool forCentralDirectory) - { - var listOfBlocks = new System.Collections.Generic.List(); - byte[] block; - - // Conditionally emit an extra field with Zip64 information. If the - // Zip64 option is Always, we emit the field, before knowing that it's - // necessary. Later, if it turns out this entry does not need zip64, - // we'll set the header ID to rubbish and the data will be ignored. - // This results in additional overhead metadata in the zip file, but - // it will be small in comparison to the entry data. - // - // On the other hand if the Zip64 option is AsNecessary and it's NOT - // for the central directory, then we do the same thing. Or, if the - // Zip64 option is AsNecessary and it IS for the central directory, - // and the entry requires zip64, then emit the header. - if (_container.Zip64 == Zip64Option.Always || - (_container.Zip64 == Zip64Option.AsNecessary && - (!forCentralDirectory || _entryRequiresZip64.Value))) - { - // add extra field for zip64 here - // workitem 7924 - int sz = 4 + (forCentralDirectory ? 28 : 16); - block = new byte[sz]; - int i = 0; - - if (_presumeZip64 || forCentralDirectory) - { - // HeaderId = always use zip64 extensions. - block[i++] = 0x01; - block[i++] = 0x00; - } - else - { - // HeaderId = dummy data now, maybe set to 0x0001 (ZIP64) later. - block[i++] = 0x99; - block[i++] = 0x99; - } - - // DataSize - block[i++] = (byte)(sz - 4); // decimal 28 or 16 (workitem 7924) - block[i++] = 0x00; - - // The actual metadata - we may or may not have real values yet... - - // uncompressed size - Array.Copy(BitConverter.GetBytes(_UncompressedSize), 0, block, i, 8); - i += 8; - // compressed size - Array.Copy(BitConverter.GetBytes(_CompressedSize), 0, block, i, 8); - i += 8; - - // workitem 7924 - only include this if the "extra" field is for - // use in the central directory. It is unnecessary and not useful - // for local header; makes WinZip choke. - if (forCentralDirectory) - { - // relative offset - Array.Copy(BitConverter.GetBytes(_RelativeOffsetOfLocalHeader), 0, block, i, 8); - i += 8; - - // starting disk number - Array.Copy(BitConverter.GetBytes(0), 0, block, i, 4); - } - listOfBlocks.Add(block); - } - - -#if AESCRYPTO - if (Encryption == EncryptionAlgorithm.WinZipAes128 || - Encryption == EncryptionAlgorithm.WinZipAes256) - { - block = new byte[4 + 7]; - int i = 0; - // extra field for WinZip AES - // header id - block[i++] = 0x01; - block[i++] = 0x99; - - // data size - block[i++] = 0x07; - block[i++] = 0x00; - - // vendor number - block[i++] = 0x01; // AE-1 - means "Verify CRC" - block[i++] = 0x00; - - // vendor id "AE" - block[i++] = 0x41; - block[i++] = 0x45; - - // key strength - int keystrength = GetKeyStrengthInBits(Encryption); - if (keystrength == 128) - block[i] = 1; - else if (keystrength == 256) - block[i] = 3; - else - block[i] = 0xFF; - i++; - - // actual compression method - block[i++] = (byte)(_CompressionMethod & 0x00FF); - block[i++] = (byte)(_CompressionMethod & 0xFF00); - - listOfBlocks.Add(block); - } -#endif - - if (_ntfsTimesAreSet && _emitNtfsTimes) - { - block = new byte[32 + 4]; - // HeaderId 2 bytes 0x000a == NTFS times - // Datasize 2 bytes 32 - // reserved 4 bytes ?? don't care - // timetag 2 bytes 0x0001 == NTFS time - // size 2 bytes 24 == 8 bytes each for ctime, mtime, atime - // mtime 8 bytes win32 ticks since win32epoch - // atime 8 bytes win32 ticks since win32epoch - // ctime 8 bytes win32 ticks since win32epoch - int i = 0; - // extra field for NTFS times - // header id - block[i++] = 0x0a; - block[i++] = 0x00; - - // data size - block[i++] = 32; - block[i++] = 0; - - i += 4; // reserved - - // time tag - block[i++] = 0x01; - block[i++] = 0x00; - - // data size (again) - block[i++] = 24; - block[i++] = 0; - - Int64 z = _Mtime.ToFileTime(); - Array.Copy(BitConverter.GetBytes(z), 0, block, i, 8); - i += 8; - z = _Atime.ToFileTime(); - Array.Copy(BitConverter.GetBytes(z), 0, block, i, 8); - i += 8; - z = _Ctime.ToFileTime(); - Array.Copy(BitConverter.GetBytes(z), 0, block, i, 8); - i += 8; - - listOfBlocks.Add(block); - } - - if (_ntfsTimesAreSet && _emitUnixTimes) - { - int len = 5 + 4; - if (!forCentralDirectory) len += 8; - - block = new byte[len]; - // local form: - // -------------- - // HeaderId 2 bytes 0x5455 == unix timestamp - // Datasize 2 bytes 13 - // flags 1 byte 7 (low three bits all set) - // mtime 4 bytes seconds since unix epoch - // atime 4 bytes seconds since unix epoch - // ctime 4 bytes seconds since unix epoch - // - // central directory form: - //--------------------------------- - // HeaderId 2 bytes 0x5455 == unix timestamp - // Datasize 2 bytes 5 - // flags 1 byte 7 (low three bits all set) - // mtime 4 bytes seconds since unix epoch - // - int i = 0; - // extra field for "unix" times - // header id - block[i++] = 0x55; - block[i++] = 0x54; - - // data size - block[i++] = unchecked((byte)(len - 4)); - block[i++] = 0; - - // flags - block[i++] = 0x07; - - Int32 z = unchecked((int)((_Mtime - _unixEpoch).TotalSeconds)); - Array.Copy(BitConverter.GetBytes(z), 0, block, i, 4); - i += 4; - if (!forCentralDirectory) - { - z = unchecked((int)((_Atime - _unixEpoch).TotalSeconds)); - Array.Copy(BitConverter.GetBytes(z), 0, block, i, 4); - i += 4; - z = unchecked((int)((_Ctime - _unixEpoch).TotalSeconds)); - Array.Copy(BitConverter.GetBytes(z), 0, block, i, 4); - i += 4; - } - listOfBlocks.Add(block); - } - - - // inject other blocks here... - - - // concatenate any blocks we've got: - byte[] aggregateBlock = null; - if (listOfBlocks.Count > 0) - { - int totalLength = 0; - int i, current = 0; - for (i = 0; i < listOfBlocks.Count; i++) - totalLength += listOfBlocks[i].Length; - aggregateBlock = new byte[totalLength]; - for (i = 0; i < listOfBlocks.Count; i++) - { - System.Array.Copy(listOfBlocks[i], 0, aggregateBlock, current, listOfBlocks[i].Length); - current += listOfBlocks[i].Length; - } - } - - return aggregateBlock; - } - - - - // private System.Text.Encoding GenerateCommentBytes() - // { - // var getEncoding = new Func({ - // switch (AlternateEncodingUsage) - // { - // case ZipOption.Always: - // return AlternateEncoding; - // case ZipOption.Never: - // return ibm437; - // } - // var cb = ibm437.GetBytes(_Comment); - // // need to use this form of GetString() for .NET CF - // string s1 = ibm437.GetString(cb, 0, cb.Length); - // if (s1 == _Comment) - // return ibm437; - // return AlternateEncoding; - // }); - // - // var encoding = getEncoding(); - // _CommentBytes = encoding.GetBytes(_Comment); - // return encoding; - // } - - - private string NormalizeFileName() - { - // here, we need to flip the backslashes to forward-slashes, - // also, we need to trim the \\server\share syntax from any UNC path. - // and finally, we need to remove any leading .\ - - string SlashFixed = FileName.Replace("\\", "/"); - string s1 = null; - if ((_TrimVolumeFromFullyQualifiedPaths) && (FileName.Length >= 3) - && (FileName[1] == ':') && (SlashFixed[2] == '/')) - { - // trim off volume letter, colon, and slash - s1 = SlashFixed.Substring(3); - } - else if ((FileName.Length >= 4) - && ((SlashFixed[0] == '/') && (SlashFixed[1] == '/'))) - { - int n = SlashFixed.IndexOf('/', 2); - if (n == -1) - throw new ArgumentException("The path for that entry appears to be badly formatted"); - s1 = SlashFixed.Substring(n + 1); - } - else if ((FileName.Length >= 3) - && ((SlashFixed[0] == '.') && (SlashFixed[1] == '/'))) - { - // trim off dot and slash - s1 = SlashFixed.Substring(2); - } - else - { - s1 = SlashFixed; - } - return s1; - } - - - /// - /// generate and return a byte array that encodes the filename - /// for the entry. - /// - /// - /// - /// side effects: generate and store into _CommentBytes the - /// byte array for any comment attached to the entry. Also - /// sets _actualEncoding to indicate the actual encoding - /// used. The same encoding is used for both filename and - /// comment. - /// - /// - private byte[] GetEncodedFileNameBytes() - { - // workitem 6513 - var s1 = NormalizeFileName(); - - switch(AlternateEncodingUsage) - { - case ZipOption.Always: - if (!(_Comment == null || _Comment.Length == 0)) - _CommentBytes = AlternateEncoding.GetBytes(_Comment); - _actualEncoding = AlternateEncoding; - return AlternateEncoding.GetBytes(s1); - - case ZipOption.Never: - if (!(_Comment == null || _Comment.Length == 0)) - _CommentBytes = ibm437.GetBytes(_Comment); - _actualEncoding = ibm437; - return ibm437.GetBytes(s1); - } - - // arriving here means AlternateEncodingUsage is "AsNecessary" - - // case ZipOption.AsNecessary: - // workitem 6513: when writing, use the alternative encoding - // only when _actualEncoding is not yet set (it can be set - // during Read), and when ibm437 will not do. - - byte[] result = ibm437.GetBytes(s1); - // need to use this form of GetString() for .NET CF - string s2 = ibm437.GetString(result, 0, result.Length); - _CommentBytes = null; - if (s2 != s1) - { - // Encoding the filename with ibm437 does not allow round-trips. - // Therefore, use the alternate encoding. Assume it will work, - // no checking of round trips here. - result = AlternateEncoding.GetBytes(s1); - if (_Comment != null && _Comment.Length != 0) - _CommentBytes = AlternateEncoding.GetBytes(_Comment); - _actualEncoding = AlternateEncoding; - return result; - } - - _actualEncoding = ibm437; - - // Using ibm437, FileName can be encoded without information - // loss; now try the Comment. - - // if there is no comment, use ibm437. - if (_Comment == null || _Comment.Length == 0) - return result; - - // there is a comment. Get the encoded form. - byte[] cbytes = ibm437.GetBytes(_Comment); - string c2 = ibm437.GetString(cbytes,0,cbytes.Length); - - // Check for round-trip. - if (c2 != Comment) - { - // Comment cannot correctly be encoded with ibm437. Use - // the alternate encoding. - - result = AlternateEncoding.GetBytes(s1); - _CommentBytes = AlternateEncoding.GetBytes(_Comment); - _actualEncoding = AlternateEncoding; - return result; - } - - // use IBM437 - _CommentBytes = cbytes; - return result; - } - - - - private bool WantReadAgain() - { - if (_UncompressedSize < 0x10) return false; - if (_CompressionMethod == 0x00) return false; - if (CompressionLevel == Ionic.Zlib.CompressionLevel.None) return false; - if (_CompressedSize < _UncompressedSize) return false; - - if (this._Source == ZipEntrySource.Stream && !this._sourceStream.CanSeek) return false; - -#if AESCRYPTO - if (_aesCrypto_forWrite != null && (CompressedSize - _aesCrypto_forWrite.SizeOfEncryptionMetadata) <= UncompressedSize + 0x10) return false; -#endif - - if (_zipCrypto_forWrite != null && (CompressedSize - 12) <= UncompressedSize) return false; - - return true; - } - - - - private void MaybeUnsetCompressionMethodForWriting(int cycle) - { - // if we've already tried with compression... turn it off this time - if (cycle > 1) - { - _CompressionMethod = 0x0; - return; - } - // compression for directories = 0x00 (No Compression) - if (IsDirectory) - { - _CompressionMethod = 0x0; - return; - } - - if (this._Source == ZipEntrySource.ZipFile) - { - return; // do nothing - } - - // If __FileDataPosition is zero, then that means we will get the data - // from a file or stream. - - // It is never possible to compress a zero-length file, so we check for - // this condition. - - if (this._Source == ZipEntrySource.Stream) - { - // workitem 7742 - if (_sourceStream != null && _sourceStream.CanSeek) - { - // Length prop will throw if CanSeek is false - long fileLength = _sourceStream.Length; - if (fileLength == 0) - { - _CompressionMethod = 0x00; - return; - } - } - } - else if ((this._Source == ZipEntrySource.FileSystem) && (SharedUtilities.GetFileLength(LocalFileName) == 0L)) - { - _CompressionMethod = 0x00; - return; - } - - // Ok, we're getting the data to be compressed from a - // non-zero-length file or stream, or a file or stream of - // unknown length, and we presume that it is non-zero. In - // that case we check the callback to see if the app wants - // to tell us whether to compress or not. - if (SetCompression != null) - CompressionLevel = SetCompression(LocalFileName, _FileNameInArchive); - - // finally, set CompressionMethod to None if CompressionLevel is None - if (CompressionLevel == (short)Ionic.Zlib.CompressionLevel.None && - CompressionMethod == Ionic.Zip.CompressionMethod.Deflate) - _CompressionMethod = 0x00; - - return; - } - - - - // write the header info for an entry - internal void WriteHeader(Stream s, int cycle) - { - // Must remember the offset, within the output stream, of this particular - // entry header. - // - // This is for 2 reasons: - // - // 1. so we can determine the RelativeOffsetOfLocalHeader (ROLH) for - // use in the central directory. - // 2. so we can seek backward in case there is an error opening or reading - // the file, and the application decides to skip the file. In this case, - // we need to seek backward in the output stream to allow the next entry - // to be added to the zipfile output stream. - // - // Normally you would just store the offset before writing to the output - // stream and be done with it. But the possibility to use split archives - // makes this approach ineffective. In split archives, each file or segment - // is bound to a max size limit, and each local file header must not span a - // segment boundary; it must be written contiguously. If it will fit in the - // current segment, then the ROLH is just the current Position in the output - // stream. If it won't fit, then we need a new file (segment) and the ROLH - // is zero. - // - // But we only can know if it is possible to write a header contiguously - // after we know the size of the local header, a size that varies with - // things like filename length, comments, and extra fields. We have to - // compute the header fully before knowing whether it will fit. - // - // That takes care of item #1 above. Now, regarding #2. If an error occurs - // while computing the local header, we want to just seek backward. The - // exception handling logic (in the caller of WriteHeader) uses ROLH to - // scroll back. - // - // All this means we have to preserve the starting offset before computing - // the header, and also we have to compute the offset later, to handle the - // case of split archives. - - var counter = s as CountingStream; - - // workitem 8098: ok (output) - // This may change later, for split archives - - // Don't set _RelativeOffsetOfLocalHeader. Instead, set a temp variable. - // This allows for re-streaming, where a zip entry might be read from a - // zip archive (and maybe decrypted, and maybe decompressed) and then - // written to another zip archive, with different settings for - // compression method, compression level, or encryption algorithm. - _future_ROLH = (counter != null) - ? counter.ComputedPosition - : s.Position; - - int j = 0, i = 0; - - byte[] block = new byte[30]; - - // signature - block[i++] = (byte)(ZipConstants.ZipEntrySignature & 0x000000FF); - block[i++] = (byte)((ZipConstants.ZipEntrySignature & 0x0000FF00) >> 8); - block[i++] = (byte)((ZipConstants.ZipEntrySignature & 0x00FF0000) >> 16); - block[i++] = (byte)((ZipConstants.ZipEntrySignature & 0xFF000000) >> 24); - - // Design notes for ZIP64: - // - // The specification says that the header must include the Compressed - // and Uncompressed sizes, as well as the CRC32 value. When creating - // a zip via streamed processing, these quantities are not known until - // after the compression is done. Thus, a typical way to do it is to - // insert zeroes for these quantities, then do the compression, then - // seek back to insert the appropriate values, then seek forward to - // the end of the file data. - // - // There is also the option of using bit 3 in the GP bitfield - to - // specify that there is a data descriptor after the file data - // containing these three quantities. - // - // This works when the size of the quantities is known, either 32-bits - // or 64 bits as with the ZIP64 extensions. - // - // With Zip64, the 4-byte fields are set to 0xffffffff, and there is a - // corresponding data block in the "extra field" that contains the - // actual Compressed, uncompressed sizes. (As well as an additional - // field, the "Relative Offset of Local Header") - // - // The problem is when the app desires to use ZIP64 extensions - // optionally, only when necessary. Suppose the library assumes no - // zip64 extensions when writing the header, then after compression - // finds that the size of the data requires zip64. At this point, the - // header, already written to the file, won't have the necessary data - // block in the "extra field". The size of the entry header is fixed, - // so it is not possible to just "add on" the zip64 data block after - // compressing the file. On the other hand, always using zip64 will - // break interoperability with many other systems and apps. - // - // The approach we take is to insert a 32-byte dummy data block in the - // extra field, whenever zip64 is to be used "as necessary". This data - // block will get the actual zip64 HeaderId and zip64 metadata if - // necessary. If not necessary, the data block will get a meaningless - // HeaderId (0x1111), and will be filled with zeroes. - // - // When zip64 is actually in use, we also need to set the - // VersionNeededToExtract field to 45. - // - // There is one additional wrinkle: using zip64 as necessary conflicts - // with output to non-seekable devices. The header is emitted and - // must indicate whether zip64 is in use, before we know if zip64 is - // necessary. Because there is no seeking, the header can never be - // changed. Therefore, on non-seekable devices, - // Zip64Option.AsNecessary is the same as Zip64Option.Always. - // - - - // version needed- see AppNote.txt. - // - // need v5.1 for PKZIP strong encryption, or v2.0 for no encryption or - // for PK encryption, 4.5 for zip64. We may reset this later, as - // necessary or zip64. - - _presumeZip64 = (_container.Zip64 == Zip64Option.Always || - (_container.Zip64 == Zip64Option.AsNecessary && !s.CanSeek)); - Int16 VersionNeededToExtract = (Int16)(_presumeZip64 ? 45 : 20); -#if BZIP - if (this.CompressionMethod == Ionic.Zip.CompressionMethod.BZip2) - VersionNeededToExtract = 46; -#endif - - // (i==4) - block[i++] = (byte)(VersionNeededToExtract & 0x00FF); - block[i++] = (byte)((VersionNeededToExtract & 0xFF00) >> 8); - - // Get byte array. Side effect: sets ActualEncoding. - // Must determine encoding before setting the bitfield. - // workitem 6513 - byte[] fileNameBytes = GetEncodedFileNameBytes(); - Int16 filenameLength = (Int16)fileNameBytes.Length; - - // general purpose bitfield - // In the current implementation, this library uses only these bits - // in the GP bitfield: - // bit 0 = if set, indicates the entry is encrypted - // bit 3 = if set, indicates the CRC, C and UC sizes follow the file data. - // bit 6 = strong encryption - for pkware's meaning of strong encryption - // bit 11 = UTF-8 encoding is used in the comment and filename - - - // Here we set or unset the encryption bit. - // _BitField may already be set, as with a ZipEntry added into ZipOutputStream, which - // has bit 3 always set. We only want to set one bit - if (_Encryption == EncryptionAlgorithm.None) - _BitField &= ~1; // encryption bit OFF - else - _BitField |= 1; // encryption bit ON - - - // workitem 7941: WinZip does not the "strong encryption" bit when using AES. - // This "Strong Encryption" is a PKWare Strong encryption thing. - // _BitField |= 0x0020; - - // set the UTF8 bit if necessary -#if SILVERLIGHT - if (_actualEncoding.WebName == "utf-8") -#else - if (_actualEncoding.CodePage == System.Text.Encoding.UTF8.CodePage) -#endif - _BitField |= 0x0800; - - // The PKZIP spec says that if bit 3 is set (0x0008) in the General - // Purpose BitField, then the CRC, Compressed size, and uncompressed - // size are written directly after the file data. - // - // These 3 quantities are normally present in the regular zip entry - // header. But, they are not knowable until after the compression is - // done. So, in the normal case, we - // - // - write the header, using zeros for these quantities - // - compress the data, and incidentally compute these quantities. - // - seek back and write the correct values them into the header. - // - // This is nice because, while it is more complicated to write the zip - // file, it is simpler and less error prone to read the zip file, and - // as a result more applications can read zip files produced this way, - // with those 3 quantities in the header. - // - // But if seeking in the output stream is not possible, then we need - // to set the appropriate bitfield and emit these quantities after the - // compressed file data in the output. - // - // workitem 7216 - having trouble formatting a zip64 file that is - // readable by WinZip. not sure why! What I found is that setting - // bit 3 and following all the implications, the zip64 file is - // readable by WinZip 12. and Perl's IO::Compress::Zip . Perl takes - // an interesting approach - it always sets bit 3 if ZIP64 in use. - // DotNetZip now does the same; this gives better compatibility with - // WinZip 12. - - if (IsDirectory || cycle == 99) - { - // (cycle == 99) indicates a zero-length entry written by ZipOutputStream - - _BitField &= ~0x0008; // unset bit 3 - no "data descriptor" - ever - _BitField &= ~0x0001; // unset bit 1 - no encryption - ever - Encryption = EncryptionAlgorithm.None; - Password = null; - } - else if (!s.CanSeek) - _BitField |= 0x0008; - -#if DONT_GO_THERE - else if (this.Encryption == EncryptionAlgorithm.PkzipWeak && - this._Source != ZipEntrySource.ZipFile) - { - // Set bit 3 to avoid the double-read perf issue. - // - // When PKZIP encryption is used, byte 11 of the encryption header is - // used as a consistency check. It is normally set to the MSByte of the - // CRC. But this means the cRC must be known ebfore compression and - // encryption, which means the entire stream has to be read twice. To - // avoid that, the high-byte of the time blob (when in DOS format) can - // be used for the consistency check (byte 11 in the encryption header). - // But this means the entry must have bit 3 set. - // - // Previously I used a more complex arrangement - using the methods like - // FigureCrc32(), PrepOutputStream() and others, in order to manage the - // seek-back in the source stream. Why? Because bit 3 is not always - // friendly with third-party zip tools, like those on the Mac. - // - // This is why this code is still ifdef'd out. - // - // Might consider making this yet another programmable option - - // AlwaysUseBit3ForPkzip. But that's for another day. - // - _BitField |= 0x0008; - } -#endif - - // (i==6) - block[i++] = (byte)(_BitField & 0x00FF); - block[i++] = (byte)((_BitField & 0xFF00) >> 8); - - // Here, we want to set values for Compressed Size, Uncompressed Size, - // and CRC. If we have __FileDataPosition as not -1 (zero is a valid - // FDP), then that means we are reading this zip entry from a zip - // file, and we have good values for those quantities. - // - // If _FileDataPosition is -1, then we are constructing this Entry - // from nothing. We zero those quantities now, and we will compute - // actual values for the three quantities later, when we do the - // compression, and then seek back to write them into the appropriate - // place in the header. - if (this.__FileDataPosition == -1) - { - //_UncompressedSize = 0; // do not unset - may need this value for restream - // _Crc32 = 0; // ditto - _CompressedSize = 0; - _crcCalculated = false; - } - - // set compression method here - MaybeUnsetCompressionMethodForWriting(cycle); - - // (i==8) compression method - block[i++] = (byte)(_CompressionMethod & 0x00FF); - block[i++] = (byte)((_CompressionMethod & 0xFF00) >> 8); - - if (cycle == 99) - { - // (cycle == 99) indicates a zero-length entry written by ZipOutputStream - SetZip64Flags(); - } - -#if AESCRYPTO - else if (Encryption == EncryptionAlgorithm.WinZipAes128 || Encryption == EncryptionAlgorithm.WinZipAes256) - { - i -= 2; - block[i++] = 0x63; - block[i++] = 0; - } -#endif - - // LastMod - _TimeBlob = Ionic.Zip.SharedUtilities.DateTimeToPacked(LastModified); - - // (i==10) time blob - block[i++] = (byte)(_TimeBlob & 0x000000FF); - block[i++] = (byte)((_TimeBlob & 0x0000FF00) >> 8); - block[i++] = (byte)((_TimeBlob & 0x00FF0000) >> 16); - block[i++] = (byte)((_TimeBlob & 0xFF000000) >> 24); - - // (i==14) CRC - if source==filesystem, this is zero now, actual value - // will be calculated later. if source==archive, this is a bonafide - // value. - block[i++] = (byte)(_Crc32 & 0x000000FF); - block[i++] = (byte)((_Crc32 & 0x0000FF00) >> 8); - block[i++] = (byte)((_Crc32 & 0x00FF0000) >> 16); - block[i++] = (byte)((_Crc32 & 0xFF000000) >> 24); - - if (_presumeZip64) - { - // (i==18) CompressedSize (Int32) and UncompressedSize - all 0xFF for now - for (j = 0; j < 8; j++) - block[i++] = 0xFF; - } - else - { - // (i==18) CompressedSize (Int32) - this value may or may not be - // bonafide. if source == filesystem, then it is zero, and we'll - // learn it after we compress. if source == archive, then it is - // bonafide data. - block[i++] = (byte)(_CompressedSize & 0x000000FF); - block[i++] = (byte)((_CompressedSize & 0x0000FF00) >> 8); - block[i++] = (byte)((_CompressedSize & 0x00FF0000) >> 16); - block[i++] = (byte)((_CompressedSize & 0xFF000000) >> 24); - - // (i==22) UncompressedSize (Int32) - this value may or may not be - // bonafide. - block[i++] = (byte)(_UncompressedSize & 0x000000FF); - block[i++] = (byte)((_UncompressedSize & 0x0000FF00) >> 8); - block[i++] = (byte)((_UncompressedSize & 0x00FF0000) >> 16); - block[i++] = (byte)((_UncompressedSize & 0xFF000000) >> 24); - } - - // (i==26) filename length (Int16) - block[i++] = (byte)(filenameLength & 0x00FF); - block[i++] = (byte)((filenameLength & 0xFF00) >> 8); - - _Extra = ConstructExtraField(false); - - // (i==28) extra field length (short) - Int16 extraFieldLength = (Int16)((_Extra == null) ? 0 : _Extra.Length); - block[i++] = (byte)(extraFieldLength & 0x00FF); - block[i++] = (byte)((extraFieldLength & 0xFF00) >> 8); - - // workitem 13542 - byte[] bytes = new byte[i + filenameLength + extraFieldLength]; - - // get the fixed portion - Buffer.BlockCopy(block, 0, bytes, 0, i); - //for (j = 0; j < i; j++) bytes[j] = block[j]; - - // The filename written to the archive. - Buffer.BlockCopy(fileNameBytes, 0, bytes, i, fileNameBytes.Length); - // for (j = 0; j < fileNameBytes.Length; j++) - // bytes[i + j] = fileNameBytes[j]; - - i += fileNameBytes.Length; - - // "Extra field" - if (_Extra != null) - { - Buffer.BlockCopy(_Extra, 0, bytes, i, _Extra.Length); - // for (j = 0; j < _Extra.Length; j++) - // bytes[i + j] = _Extra[j]; - i += _Extra.Length; - } - - _LengthOfHeader = i; - - // handle split archives - var zss = s as ZipSegmentedStream; - if (zss != null) - { - zss.ContiguousWrite = true; - UInt32 requiredSegment = zss.ComputeSegment(i); - if (requiredSegment != zss.CurrentSegment) - _future_ROLH = 0; // rollover! - else - _future_ROLH = zss.Position; - - _diskNumber = requiredSegment; - } - - // validate the ZIP64 usage - if (_container.Zip64 == Zip64Option.Never && (uint)_RelativeOffsetOfLocalHeader >= 0xFFFFFFFF) - throw new ZipException("Offset within the zip archive exceeds 0xFFFFFFFF. Consider setting the UseZip64WhenSaving property on the ZipFile instance."); - - - // finally, write the header to the stream - s.Write(bytes, 0, i); - - // now that the header is written, we can turn off the contiguous write restriction. - if (zss != null) - zss.ContiguousWrite = false; - - // Preserve this header data, we'll use it again later. - // ..when seeking backward, to write again, after we have the Crc, compressed - // and uncompressed sizes. - // ..and when writing the central directory structure. - _EntryHeader = bytes; - } - - - - - private Int32 FigureCrc32() - { - if (_crcCalculated == false) - { - Stream input = null; - // get the original stream: - if (this._Source == ZipEntrySource.WriteDelegate) - { - var output = new Ionic.Crc.CrcCalculatorStream(Stream.Null); - // allow the application to write the data - this._WriteDelegate(this.FileName, output); - _Crc32 = output.Crc; - } - else if (this._Source == ZipEntrySource.ZipFile) - { - // nothing to do - the CRC is already set - } - else - { - if (this._Source == ZipEntrySource.Stream) - { - PrepSourceStream(); - input = this._sourceStream; - } - else if (this._Source == ZipEntrySource.JitStream) - { - // allow the application to open the stream - if (this._sourceStream == null) - _sourceStream = this._OpenDelegate(this.FileName); - PrepSourceStream(); - input = this._sourceStream; - } - else if (this._Source == ZipEntrySource.ZipOutputStream) - { - } - else - { - //input = File.OpenRead(LocalFileName); - input = File.Open(LocalFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - } - - var crc32 = new Ionic.Crc.CRC32(); - _Crc32 = crc32.GetCrc32(input); - - if (_sourceStream == null) - { -#if NETCF - input.Close(); -#else - input.Dispose(); -#endif - } - } - _crcCalculated = true; - } - return _Crc32; - } - - - /// - /// Stores the position of the entry source stream, or, if the position is - /// already stored, seeks to that position. - /// - /// - /// - /// - /// This method is called in prep for reading the source stream. If PKZIP - /// encryption is used, then we need to calc the CRC32 before doing the - /// encryption, because the CRC is used in the 12th byte of the PKZIP - /// encryption header. So, we need to be able to seek backward in the source - /// when saving the ZipEntry. This method is called from the place that - /// calculates the CRC, and also from the method that does the encryption of - /// the file data. - /// - /// - /// - /// The first time through, this method sets the _sourceStreamOriginalPosition - /// field. Subsequent calls to this method seek to that position. - /// - /// - private void PrepSourceStream() - { - if (_sourceStream == null) - throw new ZipException(String.Format("The input stream is null for entry '{0}'.", FileName)); - - if (this._sourceStreamOriginalPosition != null) - { - // this will happen the 2nd cycle through, if the stream is seekable - this._sourceStream.Position = this._sourceStreamOriginalPosition.Value; - } - else if (this._sourceStream.CanSeek) - { - // this will happen the first cycle through, if seekable - this._sourceStreamOriginalPosition = new Nullable(this._sourceStream.Position); - } - else if (this.Encryption == EncryptionAlgorithm.PkzipWeak) - { - // In general, using PKZIP encryption on a a zip entry whose input - // comes from a non-seekable stream, is tricky. Here's why: - // - // Byte 11 of the PKZIP encryption header is used for password - // validation and consistency checknig. - // - // Normally, the highest byte of the CRC is used as the 11th (last) byte - // in the PKZIP encryption header. This means the CRC must be known - // before encryption is performed. Normally that means we read the full - // data stream, compute the CRC, then seek back and read it again for - // the compression+encryption phase. Obviously this is bad for - // performance with a large input file. - // - // There's a twist in the ZIP spec (actually documented only in infozip - // code, not in the spec itself) that allows the high-order byte of the - // last modified time for the entry, when the lastmod time is in packed - // (DOS) format, to be used for Byte 11 in the encryption header. In - // this case, the bit 3 "data descriptor" must be used. - // - // An intelligent implementation would therefore force the use of the - // bit 3 data descriptor when PKZIP encryption is in use, regardless. - // This avoids the double-read of the stream to be encrypted. So far, - // DotNetZip doesn't do that; it just punts when the input stream is - // non-seekable, and the output does not use Bit 3. - // - // The other option is to use the CRC when it is already available, eg, - // when the source for the data is a ZipEntry (when the zip file is - // being updated). In this case we already know the CRC and can just use - // what we know. - - if (this._Source != ZipEntrySource.ZipFile && ((this._BitField & 0x0008) != 0x0008)) - throw new ZipException("It is not possible to use PKZIP encryption on a non-seekable input stream"); - } - } - - - /// - /// Copy metadata that may have been changed by the app. We do this when - /// resetting the zipFile instance. If the app calls Save() on a ZipFile, then - /// tries to party on that file some more, we may need to Reset() it , which - /// means re-reading the entries and then copying the metadata. I think. - /// - internal void CopyMetaData(ZipEntry source) - { - this.__FileDataPosition = source.__FileDataPosition; - this.CompressionMethod = source.CompressionMethod; - this._CompressionMethod_FromZipFile = source._CompressionMethod_FromZipFile; - this._CompressedFileDataSize = source._CompressedFileDataSize; - this._UncompressedSize = source._UncompressedSize; - this._BitField = source._BitField; - this._Source = source._Source; - this._LastModified = source._LastModified; - this._Mtime = source._Mtime; - this._Atime = source._Atime; - this._Ctime = source._Ctime; - this._ntfsTimesAreSet = source._ntfsTimesAreSet; - this._emitUnixTimes = source._emitUnixTimes; - this._emitNtfsTimes = source._emitNtfsTimes; - } - - - private void OnWriteBlock(Int64 bytesXferred, Int64 totalBytesToXfer) - { - if (_container.ZipFile != null) - _ioOperationCanceled = _container.ZipFile.OnSaveBlock(this, bytesXferred, totalBytesToXfer); - } - - - - private void _WriteEntryData(Stream s) - { - // Read in the data from the input stream (often a file in the filesystem), - // and write it to the output stream, calculating a CRC on it as we go. - // We will also compress and encrypt as necessary. - - Stream input = null; - long fdp = -1L; - try - { - // Want to record the position in the zip file of the zip entry - // data (as opposed to the metadata). s.Position may fail on some - // write-only streams, eg stdout or System.Web.HttpResponseStream. - // We swallow that exception, because we don't care, in that case. - // But, don't set __FileDataPosition directly. It may be needed - // to READ the zip entry from the zip file, if this is a - // "re-stream" situation. In other words if the zip entry has - // changed compression level, or compression method, or (maybe?) - // encryption algorithm. In that case if the original entry is - // encrypted, we need __FileDataPosition to be the value for the - // input zip file. This s.Position is for the output zipfile. So - // we copy fdp to __FileDataPosition after this entry has been - // (maybe) restreamed. - fdp = s.Position; - } - catch (Exception) { } - - try - { - // Use fileLength for progress updates, and to decide whether we can - // skip encryption and compression altogether (in case of length==zero) - long fileLength = SetInputAndFigureFileLength(ref input); - - // Wrap a counting stream around the raw output stream: - // This is the last thing that happens before the bits go to the - // application-provided stream. - // - // Sometimes s is a CountingStream. Doesn't matter. Wrap it with a - // counter anyway. We need to count at both levels. - - CountingStream entryCounter = new CountingStream(s); - - Stream encryptor; - Stream compressor; - - if (fileLength != 0L) - { - // Maybe wrap an encrypting stream around the counter: This will - // happen BEFORE output counting, and AFTER compression, if encryption - // is used. - encryptor = MaybeApplyEncryption(entryCounter); - - // Maybe wrap a compressing Stream around that. - // This will happen BEFORE encryption (if any) as we write data out. - compressor = MaybeApplyCompression(encryptor, fileLength); - } - else - { - encryptor = compressor = entryCounter; - } - - // Wrap a CrcCalculatorStream around that. - // This will happen BEFORE compression (if any) as we write data out. - var output = new Ionic.Crc.CrcCalculatorStream(compressor, true); - - // output.Write() causes this flow: - // calc-crc -> compress -> encrypt -> count -> actually write - - if (this._Source == ZipEntrySource.WriteDelegate) - { - // allow the application to write the data - this._WriteDelegate(this.FileName, output); - } - else - { - // synchronously copy the input stream to the output stream-chain - byte[] buffer = new byte[BufferSize]; - int n; - while ((n = SharedUtilities.ReadWithRetry(input, buffer, 0, buffer.Length, FileName)) != 0) - { - output.Write(buffer, 0, n); - OnWriteBlock(output.TotalBytesSlurped, fileLength); - if (_ioOperationCanceled) - break; - } - } - - FinishOutputStream(s, entryCounter, encryptor, compressor, output); - } - finally - { - if (this._Source == ZipEntrySource.JitStream) - { - // allow the application to close the stream - if (this._CloseDelegate != null) - this._CloseDelegate(this.FileName, input); - } - else if ((input as FileStream) != null) - { -#if NETCF - input.Close(); -#else - input.Dispose(); -#endif - } - } - - if (_ioOperationCanceled) - return; - - // set FDP now, to allow for re-streaming - this.__FileDataPosition = fdp; - PostProcessOutput(s); - } - - - /// - /// Set the input stream and get its length, if possible. The length is - /// used for progress updates, AND, to allow an optimization in case of - /// a stream/file of zero length. In that case we skip the Encrypt and - /// compression Stream. (like DeflateStream or BZip2OutputStream) - /// - private long SetInputAndFigureFileLength(ref Stream input) - { - long fileLength = -1L; - // get the original stream: - if (this._Source == ZipEntrySource.Stream) - { - PrepSourceStream(); - input = this._sourceStream; - - // Try to get the length, no big deal if not available. - try { fileLength = this._sourceStream.Length; } - catch (NotSupportedException) { } - } - else if (this._Source == ZipEntrySource.ZipFile) - { - // we are "re-streaming" the zip entry. - string pwd = (_Encryption_FromZipFile == EncryptionAlgorithm.None) ? null : (this._Password ?? this._container.Password); - this._sourceStream = InternalOpenReader(pwd); - PrepSourceStream(); - input = this._sourceStream; - fileLength = this._sourceStream.Length; - } - else if (this._Source == ZipEntrySource.JitStream) - { - // allow the application to open the stream - if (this._sourceStream == null) _sourceStream = this._OpenDelegate(this.FileName); - PrepSourceStream(); - input = this._sourceStream; - try { fileLength = this._sourceStream.Length; } - catch (NotSupportedException) { } - } - else if (this._Source == ZipEntrySource.FileSystem) - { - // workitem 7145 - FileShare fs = FileShare.ReadWrite; -#if !NETCF - // FileShare.Delete is not defined for the Compact Framework - fs |= FileShare.Delete; -#endif - // workitem 8423 - input = File.Open(LocalFileName, FileMode.Open, FileAccess.Read, fs); - fileLength = input.Length; - } - - return fileLength; - } - - - - internal void FinishOutputStream(Stream s, - CountingStream entryCounter, - Stream encryptor, - Stream compressor, - Ionic.Crc.CrcCalculatorStream output) - { - if (output == null) return; - - output.Close(); - - // by calling Close() on the deflate stream, we write the footer bytes, as necessary. - if ((compressor as Ionic.Zlib.DeflateStream) != null) - compressor.Close(); -#if BZIP - else if ((compressor as Ionic.BZip2.BZip2OutputStream) != null) - compressor.Close(); -#if !NETCF - else if ((compressor as Ionic.BZip2.ParallelBZip2OutputStream) != null) - compressor.Close(); -#endif -#endif - -#if !NETCF - else if ((compressor as Ionic.Zlib.ParallelDeflateOutputStream) != null) - compressor.Close(); -#endif - - encryptor.Flush(); - encryptor.Close(); - - _LengthOfTrailer = 0; - - _UncompressedSize = output.TotalBytesSlurped; - -#if AESCRYPTO - WinZipAesCipherStream wzacs = encryptor as WinZipAesCipherStream; - if (wzacs != null && _UncompressedSize > 0) - { - s.Write(wzacs.FinalAuthentication, 0, 10); - _LengthOfTrailer += 10; - } -#endif - _CompressedFileDataSize = entryCounter.BytesWritten; - _CompressedSize = _CompressedFileDataSize; // may be adjusted - _Crc32 = output.Crc; - - // Set _RelativeOffsetOfLocalHeader now, to allow for re-streaming - StoreRelativeOffset(); - } - - - - - internal void PostProcessOutput(Stream s) - { - var s1 = s as CountingStream; - - // workitem 8931 - for WriteDelegate. - // The WriteDelegate changes things because there can be a zero-byte stream - // written. In all other cases DotNetZip knows the length of the stream - // before compressing and encrypting. In this case we have to circle back, - // and omit all the crypto stuff - the GP bitfield, and the crypto header. - if (_UncompressedSize == 0 && _CompressedSize == 0) - { - if (this._Source == ZipEntrySource.ZipOutputStream) return; // nothing to do... - - if (_Password != null) - { - int headerBytesToRetract = 0; - if (Encryption == EncryptionAlgorithm.PkzipWeak) - headerBytesToRetract = 12; -#if AESCRYPTO - else if (Encryption == EncryptionAlgorithm.WinZipAes128 || - Encryption == EncryptionAlgorithm.WinZipAes256) - { - headerBytesToRetract = _aesCrypto_forWrite._Salt.Length + _aesCrypto_forWrite.GeneratedPV.Length; - } -#endif - if (this._Source == ZipEntrySource.ZipOutputStream && !s.CanSeek) - throw new ZipException("Zero bytes written, encryption in use, and non-seekable output."); - - if (Encryption != EncryptionAlgorithm.None) - { - // seek back in the stream to un-output the security metadata - s.Seek(-1 * headerBytesToRetract, SeekOrigin.Current); - s.SetLength(s.Position); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(s); - - // workitem 11131 - // adjust the count on the CountingStream as necessary - if (s1 != null) s1.Adjust(headerBytesToRetract); - - // subtract the size of the security header from the _LengthOfHeader - _LengthOfHeader -= headerBytesToRetract; - __FileDataPosition -= headerBytesToRetract; - } - _Password = null; - - // turn off the encryption bit - _BitField &= ~(0x0001); - - // copy the updated bitfield value into the header - int j = 6; - _EntryHeader[j++] = (byte)(_BitField & 0x00FF); - _EntryHeader[j++] = (byte)((_BitField & 0xFF00) >> 8); - -#if AESCRYPTO - if (Encryption == EncryptionAlgorithm.WinZipAes128 || - Encryption == EncryptionAlgorithm.WinZipAes256) - { - // Fix the extra field - overwrite the 0x9901 headerId - // with dummy data. (arbitrarily, 0x9999) - Int16 fnLength = (short)(_EntryHeader[26] + _EntryHeader[27] * 256); - int offx = 30 + fnLength; - int aesIndex = FindExtraFieldSegment(_EntryHeader, offx, 0x9901); - if (aesIndex >= 0) - { - _EntryHeader[aesIndex++] = 0x99; - _EntryHeader[aesIndex++] = 0x99; - } - } -#endif - } - - CompressionMethod = 0; - Encryption = EncryptionAlgorithm.None; - } - else if (_zipCrypto_forWrite != null -#if AESCRYPTO - || _aesCrypto_forWrite != null -#endif - ) - - { - if (Encryption == EncryptionAlgorithm.PkzipWeak) - { - _CompressedSize += 12; // 12 extra bytes for the encryption header - } -#if AESCRYPTO - else if (Encryption == EncryptionAlgorithm.WinZipAes128 || - Encryption == EncryptionAlgorithm.WinZipAes256) - { - // adjust the compressed size to include the variable (salt+pv) - // security header and 10-byte trailer. According to the winzip AES - // spec, that metadata is included in the "Compressed Size" figure - // when encoding the zip archive. - _CompressedSize += _aesCrypto_forWrite.SizeOfEncryptionMetadata; - } -#endif - } - - int i = 8; - _EntryHeader[i++] = (byte)(_CompressionMethod & 0x00FF); - _EntryHeader[i++] = (byte)((_CompressionMethod & 0xFF00) >> 8); - - i = 14; - // CRC - the correct value now - _EntryHeader[i++] = (byte)(_Crc32 & 0x000000FF); - _EntryHeader[i++] = (byte)((_Crc32 & 0x0000FF00) >> 8); - _EntryHeader[i++] = (byte)((_Crc32 & 0x00FF0000) >> 16); - _EntryHeader[i++] = (byte)((_Crc32 & 0xFF000000) >> 24); - - SetZip64Flags(); - - // (i==26) filename length (Int16) - Int16 filenameLength = (short)(_EntryHeader[26] + _EntryHeader[27] * 256); - Int16 extraFieldLength = (short)(_EntryHeader[28] + _EntryHeader[29] * 256); - - if (_OutputUsesZip64.Value) - { - // VersionNeededToExtract - set to 45 to indicate zip64 - _EntryHeader[4] = (byte)(45 & 0x00FF); - _EntryHeader[5] = 0x00; - - // workitem 7924 - don't need bit 3 - // // workitem 7917 - // // set bit 3 for ZIP64 compatibility with WinZip12 - // _BitField |= 0x0008; - // _EntryHeader[6] = (byte)(_BitField & 0x00FF); - - // CompressedSize and UncompressedSize - 0xFF - for (int j = 0; j < 8; j++) - _EntryHeader[i++] = 0xff; - - // At this point we need to find the "Extra field" that follows the - // filename. We had already emitted it, but the data (uncomp, comp, - // ROLH) was not available at the time we did so. Here, we emit it - // again, with final values. - - i = 30 + filenameLength; - _EntryHeader[i++] = 0x01; // zip64 - _EntryHeader[i++] = 0x00; - - i += 2; // skip over data size, which is 16+4 - - Array.Copy(BitConverter.GetBytes(_UncompressedSize), 0, _EntryHeader, i, 8); - i += 8; - Array.Copy(BitConverter.GetBytes(_CompressedSize), 0, _EntryHeader, i, 8); - } - else - { - // VersionNeededToExtract - reset to 20 since no zip64 - _EntryHeader[4] = (byte)(20 & 0x00FF); - _EntryHeader[5] = 0x00; - - // CompressedSize - the correct value now - i = 18; - _EntryHeader[i++] = (byte)(_CompressedSize & 0x000000FF); - _EntryHeader[i++] = (byte)((_CompressedSize & 0x0000FF00) >> 8); - _EntryHeader[i++] = (byte)((_CompressedSize & 0x00FF0000) >> 16); - _EntryHeader[i++] = (byte)((_CompressedSize & 0xFF000000) >> 24); - - // UncompressedSize - the correct value now - _EntryHeader[i++] = (byte)(_UncompressedSize & 0x000000FF); - _EntryHeader[i++] = (byte)((_UncompressedSize & 0x0000FF00) >> 8); - _EntryHeader[i++] = (byte)((_UncompressedSize & 0x00FF0000) >> 16); - _EntryHeader[i++] = (byte)((_UncompressedSize & 0xFF000000) >> 24); - - // The HeaderId in the extra field header, is already dummied out. - if (extraFieldLength != 0) - { - i = 30 + filenameLength; - // For zip archives written by this library, if the zip64 - // header exists, it is the first header. Because of the logic - // used when first writing the _EntryHeader bytes, the - // HeaderId is not guaranteed to be any particular value. So - // we determine if the first header is a putative zip64 header - // by examining the datasize. UInt16 HeaderId = - // (UInt16)(_EntryHeader[i] + _EntryHeader[i + 1] * 256); - Int16 DataSize = (short)(_EntryHeader[i + 2] + _EntryHeader[i + 3] * 256); - if (DataSize == 16) - { - // reset to Header Id to dummy value, effectively dummy-ing out the zip64 metadata - _EntryHeader[i++] = 0x99; - _EntryHeader[i++] = 0x99; - } - } - } - - -#if AESCRYPTO - - if (Encryption == EncryptionAlgorithm.WinZipAes128 || - Encryption == EncryptionAlgorithm.WinZipAes256) - { - // Must set compressionmethod to 0x0063 (decimal 99) - // - // and then set the compression method bytes inside the extra - // field to the actual compression method value. - - i = 8; - _EntryHeader[i++] = 0x63; - _EntryHeader[i++] = 0; - - i = 30 + filenameLength; - do - { - UInt16 HeaderId = (UInt16)(_EntryHeader[i] + _EntryHeader[i + 1] * 256); - Int16 DataSize = (short)(_EntryHeader[i + 2] + _EntryHeader[i + 3] * 256); - if (HeaderId != 0x9901) - { - // skip this header - i += DataSize + 4; - } - else - { - i += 9; - // actual compression method - _EntryHeader[i++] = (byte)(_CompressionMethod & 0x00FF); - _EntryHeader[i++] = (byte)(_CompressionMethod & 0xFF00); - } - } while (i < (extraFieldLength - 30 - filenameLength)); - } -#endif - - // finally, write the data. - - // workitem 7216 - sometimes we don't seek even if we CAN. ASP.NET - // Response.OutputStream, or stdout are non-seekable. But we may also want - // to NOT seek in other cases, eg zip64. For all cases, we just check bit 3 - // to see if we want to seek. There's one exception - if using a - // ZipOutputStream, and PKZip encryption is in use, then we set bit 3 even - // if the out is seekable. This is so the check on the last byte of the - // PKZip Encryption Header can be done on the current time, as opposed to - // the CRC, to prevent streaming the file twice. So, test for - // ZipOutputStream and seekable, and if so, seek back, even if bit 3 is set. - - if ((_BitField & 0x0008) != 0x0008 || - (this._Source == ZipEntrySource.ZipOutputStream && s.CanSeek)) - { - // seek back and rewrite the entry header - var zss = s as ZipSegmentedStream; - if (zss != null && _diskNumber != zss.CurrentSegment) - { - // In this case the entry header is in a different file, - // which has already been closed. Need to re-open it. - using (Stream hseg = ZipSegmentedStream.ForUpdate(this._container.ZipFile.Name, _diskNumber)) - { - hseg.Seek(this._RelativeOffsetOfLocalHeader, SeekOrigin.Begin); - hseg.Write(_EntryHeader, 0, _EntryHeader.Length); - } - } - else - { - // seek in the raw output stream, to the beginning of the header for - // this entry. - // workitem 8098: ok (output) - s.Seek(this._RelativeOffsetOfLocalHeader, SeekOrigin.Begin); - - // write the updated header to the output stream - s.Write(_EntryHeader, 0, _EntryHeader.Length); - - // adjust the count on the CountingStream as necessary - if (s1 != null) s1.Adjust(_EntryHeader.Length); - - // seek in the raw output stream, to the end of the file data - // for this entry - s.Seek(_CompressedSize, SeekOrigin.Current); - } - } - - // emit the descriptor - only if not a directory. - if (((_BitField & 0x0008) == 0x0008) && !IsDirectory) - { - byte[] Descriptor = new byte[16 + (_OutputUsesZip64.Value ? 8 : 0)]; - i = 0; - - // signature - Array.Copy(BitConverter.GetBytes(ZipConstants.ZipEntryDataDescriptorSignature), 0, Descriptor, i, 4); - i += 4; - - // CRC - the correct value now - Array.Copy(BitConverter.GetBytes(_Crc32), 0, Descriptor, i, 4); - i += 4; - - // workitem 7917 - if (_OutputUsesZip64.Value) - { - // CompressedSize - the correct value now - Array.Copy(BitConverter.GetBytes(_CompressedSize), 0, Descriptor, i, 8); - i += 8; - - // UncompressedSize - the correct value now - Array.Copy(BitConverter.GetBytes(_UncompressedSize), 0, Descriptor, i, 8); - i += 8; - } - else - { - // CompressedSize - (lower 32 bits) the correct value now - Descriptor[i++] = (byte)(_CompressedSize & 0x000000FF); - Descriptor[i++] = (byte)((_CompressedSize & 0x0000FF00) >> 8); - Descriptor[i++] = (byte)((_CompressedSize & 0x00FF0000) >> 16); - Descriptor[i++] = (byte)((_CompressedSize & 0xFF000000) >> 24); - - // UncompressedSize - (lower 32 bits) the correct value now - Descriptor[i++] = (byte)(_UncompressedSize & 0x000000FF); - Descriptor[i++] = (byte)((_UncompressedSize & 0x0000FF00) >> 8); - Descriptor[i++] = (byte)((_UncompressedSize & 0x00FF0000) >> 16); - Descriptor[i++] = (byte)((_UncompressedSize & 0xFF000000) >> 24); - } - - // finally, write the trailing descriptor to the output stream - s.Write(Descriptor, 0, Descriptor.Length); - - _LengthOfTrailer += Descriptor.Length; - } - } - - - - private void SetZip64Flags() - { - // zip64 housekeeping - _entryRequiresZip64 = new Nullable - (_CompressedSize >= 0xFFFFFFFF || _UncompressedSize >= 0xFFFFFFFF || _RelativeOffsetOfLocalHeader >= 0xFFFFFFFF); - - // validate the ZIP64 usage - if (_container.Zip64 == Zip64Option.Never && _entryRequiresZip64.Value) - throw new ZipException("Compressed or Uncompressed size, or offset exceeds the maximum value. Consider setting the UseZip64WhenSaving property on the ZipFile instance."); - - _OutputUsesZip64 = new Nullable(_container.Zip64 == Zip64Option.Always || _entryRequiresZip64.Value); - } - - - - /// - /// Prepare the given stream for output - wrap it in a CountingStream, and - /// then in a CRC stream, and an encryptor and deflator as appropriate. - /// - /// - /// - /// Previously this was used in ZipEntry.Write(), but in an effort to - /// introduce some efficiencies in that method I've refactored to put the - /// code inline. This method still gets called by ZipOutputStream. - /// - /// - internal void PrepOutputStream(Stream s, - long streamLength, - out CountingStream outputCounter, - out Stream encryptor, - out Stream compressor, - out Ionic.Crc.CrcCalculatorStream output) - { - TraceWriteLine("PrepOutputStream: e({0}) comp({1}) crypto({2}) zf({3})", - FileName, - CompressionLevel, - Encryption, - _container.Name); - - // Wrap a counting stream around the raw output stream: - // This is the last thing that happens before the bits go to the - // application-provided stream. - outputCounter = new CountingStream(s); - - // Sometimes the incoming "raw" output stream is already a CountingStream. - // Doesn't matter. Wrap it with a counter anyway. We need to count at both - // levels. - - if (streamLength != 0L) - { - // Maybe wrap an encrypting stream around that: - // This will happen BEFORE output counting, and AFTER deflation, if encryption - // is used. - encryptor = MaybeApplyEncryption(outputCounter); - - // Maybe wrap a compressing Stream around that. - // This will happen BEFORE encryption (if any) as we write data out. - compressor = MaybeApplyCompression(encryptor, streamLength); - } - else - { - encryptor = compressor = outputCounter; - } - // Wrap a CrcCalculatorStream around that. - // This will happen BEFORE compression (if any) as we write data out. - output = new Ionic.Crc.CrcCalculatorStream(compressor, true); - } - - - - private Stream MaybeApplyCompression(Stream s, long streamLength) - { - if (_CompressionMethod == 0x08 && CompressionLevel != Ionic.Zlib.CompressionLevel.None) - { -#if !NETCF - // ParallelDeflateThreshold == 0 means ALWAYS use parallel deflate - // ParallelDeflateThreshold == -1L means NEVER use parallel deflate - // Other values specify the actual threshold. - if (_container.ParallelDeflateThreshold == 0L || - (streamLength > _container.ParallelDeflateThreshold && - _container.ParallelDeflateThreshold > 0L)) - { - // This is sort of hacky. - // - // It's expensive to create a ParallelDeflateOutputStream, because - // of the large memory buffers. But the class is unlike most Stream - // classes in that it can be re-used, so the caller can compress - // multiple files with it, one file at a time. The key is to call - // Reset() on it, in between uses. - // - // The ParallelDeflateOutputStream is attached to the container - // itself - there is just one for the entire ZipFile or - // ZipOutputStream. So it gets created once, per save, and then - // re-used many times. - // - // This approach will break when we go to a "parallel save" - // approach, where multiple entries within the zip file are being - // compressed and saved at the same time. But for now it's ok. - // - - // instantiate the ParallelDeflateOutputStream - if (_container.ParallelDeflater == null) - { - _container.ParallelDeflater = - new Ionic.Zlib.ParallelDeflateOutputStream(s, - CompressionLevel, - _container.Strategy, - true); - // can set the codec buffer size only before the first call to Write(). - if (_container.CodecBufferSize > 0) - _container.ParallelDeflater.BufferSize = _container.CodecBufferSize; - if (_container.ParallelDeflateMaxBufferPairs > 0) - _container.ParallelDeflater.MaxBufferPairs = - _container.ParallelDeflateMaxBufferPairs; - } - // reset it with the new stream - Ionic.Zlib.ParallelDeflateOutputStream o1 = _container.ParallelDeflater; - o1.Reset(s); - return o1; - } -#endif - var o = new Ionic.Zlib.DeflateStream(s, Ionic.Zlib.CompressionMode.Compress, - CompressionLevel, - true); - if (_container.CodecBufferSize > 0) - o.BufferSize = _container.CodecBufferSize; - o.Strategy = _container.Strategy; - return o; - } - - -#if BZIP - if (_CompressionMethod == 0x0c) - { -#if !NETCF - if (_container.ParallelDeflateThreshold == 0L || - (streamLength > _container.ParallelDeflateThreshold && - _container.ParallelDeflateThreshold > 0L)) - { - - var o1 = new Ionic.BZip2.ParallelBZip2OutputStream(s, true); - return o1; - } -#endif - var o = new Ionic.BZip2.BZip2OutputStream(s, true); - return o; - } -#endif - - return s; - } - - - - private Stream MaybeApplyEncryption(Stream s) - { - if (Encryption == EncryptionAlgorithm.PkzipWeak) - { - TraceWriteLine("MaybeApplyEncryption: e({0}) PKZIP", FileName); - - return new ZipCipherStream(s, _zipCrypto_forWrite, CryptoMode.Encrypt); - } -#if AESCRYPTO - if (Encryption == EncryptionAlgorithm.WinZipAes128 || - Encryption == EncryptionAlgorithm.WinZipAes256) - { - TraceWriteLine("MaybeApplyEncryption: e({0}) AES", FileName); - - return new WinZipAesCipherStream(s, _aesCrypto_forWrite, CryptoMode.Encrypt); - } -#endif - TraceWriteLine("MaybeApplyEncryption: e({0}) None", FileName); - - return s; - } - - - - private void OnZipErrorWhileSaving(Exception e) - { - if (_container.ZipFile != null) - _ioOperationCanceled = _container.ZipFile.OnZipErrorSaving(this, e); - } - - - - internal void Write(Stream s) - { - var cs1 = s as CountingStream; - var zss1 = s as ZipSegmentedStream; - - bool done = false; - do - { - try - { - // When the app is updating a zip file, it may be possible to - // just copy data for a ZipEntry from the source zipfile to the - // destination, as a block, without decompressing and - // recompressing, etc. But, in some cases the app modifies the - // properties on a ZipEntry prior to calling Save(). A change to - // any of the metadata - the FileName, CompressioLeve and so on, - // means DotNetZip cannot simply copy through the existing - // ZipEntry data unchanged. - // - // There are two cases: - // - // 1. Changes to only metadata, which means the header and - // central directory must be changed. - // - // 2. Changes to the properties that affect the compressed - // stream, such as CompressionMethod, CompressionLevel, or - // EncryptionAlgorithm. In this case, DotNetZip must - // "re-stream" the data: the old entry data must be maybe - // decrypted, maybe decompressed, then maybe re-compressed - // and maybe re-encrypted. - // - // This test checks if the source for the entry data is a zip file, and - // if a restream is necessary. If NOT, then it just copies through - // one entry, potentially changing the metadata. - - if (_Source == ZipEntrySource.ZipFile && !_restreamRequiredOnSave) - { - CopyThroughOneEntry(s); - return; - } - - // Is the entry a directory? If so, the write is relatively simple. - if (IsDirectory) - { - WriteHeader(s, 1); - StoreRelativeOffset(); - _entryRequiresZip64 = new Nullable(_RelativeOffsetOfLocalHeader >= 0xFFFFFFFF); - _OutputUsesZip64 = new Nullable(_container.Zip64 == Zip64Option.Always || _entryRequiresZip64.Value); - // handle case for split archives - if (zss1 != null) - _diskNumber = zss1.CurrentSegment; - - return; - } - - // At this point, the source for this entry is not a directory, and - // not a previously created zip file, or the source for the entry IS - // a previously created zip but the settings whave changed in - // important ways and therefore we will need to process the - // bytestream (compute crc, maybe compress, maybe encrypt) in order - // to write the content into the new zip. - // - // We do this in potentially 2 passes: The first time we do it as - // requested, maybe with compression and maybe encryption. If that - // causes the bytestream to inflate in size, and if compression was - // on, then we turn off compression and do it again. - - - bool readAgain = true; - int nCycles = 0; - do - { - nCycles++; - - WriteHeader(s, nCycles); - - // write the encrypted header - WriteSecurityMetadata(s); - - // write the (potentially compressed, potentially encrypted) file data - _WriteEntryData(s); - - // track total entry size (including the trailing descriptor and MAC) - _TotalEntrySize = _LengthOfHeader + _CompressedFileDataSize + _LengthOfTrailer; - - // The file data has now been written to the stream, and - // the file pointer is positioned directly after file data. - - if (nCycles > 1) readAgain = false; - else if (!s.CanSeek) readAgain = false; - else readAgain = WantReadAgain(); - - if (readAgain) - { - // Seek back in the raw output stream, to the beginning of the file - // data for this entry. - - // handle case for split archives - if (zss1 != null) - { - // Console.WriteLine("***_diskNumber/first: {0}", _diskNumber); - // Console.WriteLine("***_diskNumber/current: {0}", zss.CurrentSegment); - zss1.TruncateBackward(_diskNumber, _RelativeOffsetOfLocalHeader); - } - else - // workitem 8098: ok (output). - s.Seek(_RelativeOffsetOfLocalHeader, SeekOrigin.Begin); - - // If the last entry expands, we read again; but here, we must - // truncate the stream to prevent garbage data after the - // end-of-central-directory. - - // workitem 8098: ok (output). - s.SetLength(s.Position); - - // Adjust the count on the CountingStream as necessary. - if (cs1 != null) cs1.Adjust(_TotalEntrySize); - } - } - while (readAgain); - _skippedDuringSave = false; - done = true; - } - catch (System.Exception exc1) - { - ZipErrorAction orig = this.ZipErrorAction; - int loop = 0; - do - { - if (ZipErrorAction == ZipErrorAction.Throw) - throw; - - if (ZipErrorAction == ZipErrorAction.Skip || - ZipErrorAction == ZipErrorAction.Retry) - { - // must reset file pointer here. - // workitem 13903 - seek back only when necessary - long p1 = (cs1 != null) - ? cs1.ComputedPosition - : s.Position; - long delta = p1 - _future_ROLH; - if (delta > 0) - { - s.Seek(delta, SeekOrigin.Current); // may throw - long p2 = s.Position; - s.SetLength(s.Position); // to prevent garbage if this is the last entry - if (cs1 != null) cs1.Adjust(p1 - p2); - } - if (ZipErrorAction == ZipErrorAction.Skip) - { - WriteStatus("Skipping file {0} (exception: {1})", LocalFileName, exc1.ToString()); - - _skippedDuringSave = true; - done = true; - } - else - this.ZipErrorAction = orig; - break; - } - - if (loop > 0) throw; - - if (ZipErrorAction == ZipErrorAction.InvokeErrorEvent) - { - OnZipErrorWhileSaving(exc1); - if (_ioOperationCanceled) - { - done = true; - break; - } - } - loop++; - } - while (true); - } - } - while (!done); - } - - - internal void StoreRelativeOffset() - { - _RelativeOffsetOfLocalHeader = _future_ROLH; - } - - - - internal void NotifySaveComplete() - { - // When updating a zip file, there are two contexts for properties - // like Encryption or CompressionMethod - the values read from the - // original zip file, and the values used in the updated zip file. - // The _FromZipFile versions are the originals. At the end of a save, - // these values are the same. So we need to update them. This takes - // care of the boundary case where a single zipfile instance can be - // saved multiple times, with distinct changes to the properties on - // the entries, in between each Save(). - _Encryption_FromZipFile = _Encryption; - _CompressionMethod_FromZipFile = _CompressionMethod; - _restreamRequiredOnSave = false; - _metadataChanged = false; - //_Source = ZipEntrySource.None; - _Source = ZipEntrySource.ZipFile; // workitem 10694 - } - - - internal void WriteSecurityMetadata(Stream outstream) - { - if (Encryption == EncryptionAlgorithm.None) - return; - - string pwd = this._Password; - - // special handling for source == ZipFile. - // Want to support the case where we re-stream an encrypted entry. This will involve, - // at runtime, reading, decrypting, and decompressing from the original zip file, then - // compressing, encrypting, and writing to the output zip file. - - // If that's what we're doing, and the password hasn't been set on the entry, - // we use the container (ZipFile/ZipOutputStream) password to decrypt. - // This test here says to use the container password to re-encrypt, as well, - // with that password, if the entry password is null. - - if (this._Source == ZipEntrySource.ZipFile && pwd == null) - pwd = this._container.Password; - - if (pwd == null) - { - _zipCrypto_forWrite = null; -#if AESCRYPTO - _aesCrypto_forWrite = null; -#endif - return; - } - - TraceWriteLine("WriteSecurityMetadata: e({0}) crypto({1}) pw({2})", - FileName, Encryption.ToString(), pwd); - - if (Encryption == EncryptionAlgorithm.PkzipWeak) - { - // If PKZip (weak) encryption is in use, then the encrypted entry data - // is preceded by 12-byte "encryption header" for the entry. - - _zipCrypto_forWrite = ZipCrypto.ForWrite(pwd); - - // generate the random 12-byte header: - var rnd = new System.Random(); - byte[] encryptionHeader = new byte[12]; - rnd.NextBytes(encryptionHeader); - - // workitem 8271 - if ((this._BitField & 0x0008) == 0x0008) - { - // In the case that bit 3 of the general purpose bit flag is set to - // indicate the presence of a 'data descriptor' (signature - // 0x08074b50), the last byte of the decrypted header is sometimes - // compared with the high-order byte of the lastmodified time, - // rather than the high-order byte of the CRC, to verify the - // password. - // - // This is not documented in the PKWare Appnote.txt. - // This was discovered this by analysis of the Crypt.c source file in the - // InfoZip library - // http://www.info-zip.org/pub/infozip/ - - // Also, winzip insists on this! - _TimeBlob = Ionic.Zip.SharedUtilities.DateTimeToPacked(LastModified); - encryptionHeader[11] = (byte)((this._TimeBlob >> 8) & 0xff); - } - else - { - // When bit 3 is not set, the CRC value is required before - // encryption of the file data begins. In this case there is no way - // around it: must read the stream in its entirety to compute the - // actual CRC before proceeding. - FigureCrc32(); - encryptionHeader[11] = (byte)((this._Crc32 >> 24) & 0xff); - } - - // Encrypt the random header, INCLUDING the final byte which is either - // the high-order byte of the CRC32, or the high-order byte of the - // _TimeBlob. Must do this BEFORE encrypting the file data. This - // step changes the state of the cipher, or in the words of the PKZIP - // spec, it "further initializes" the cipher keys. - - byte[] cipherText = _zipCrypto_forWrite.EncryptMessage(encryptionHeader, encryptionHeader.Length); - - // Write the ciphered bonafide encryption header. - outstream.Write(cipherText, 0, cipherText.Length); - _LengthOfHeader += cipherText.Length; // 12 bytes - } - -#if AESCRYPTO - else if (Encryption == EncryptionAlgorithm.WinZipAes128 || - Encryption == EncryptionAlgorithm.WinZipAes256) - { - // If WinZip AES encryption is in use, then the encrypted entry data is - // preceded by a variable-sized Salt and a 2-byte "password - // verification" value for the entry. - - int keystrength = GetKeyStrengthInBits(Encryption); - _aesCrypto_forWrite = WinZipAesCrypto.Generate(pwd, keystrength); - outstream.Write(_aesCrypto_forWrite.Salt, 0, _aesCrypto_forWrite._Salt.Length); - outstream.Write(_aesCrypto_forWrite.GeneratedPV, 0, _aesCrypto_forWrite.GeneratedPV.Length); - _LengthOfHeader += _aesCrypto_forWrite._Salt.Length + _aesCrypto_forWrite.GeneratedPV.Length; - - TraceWriteLine("WriteSecurityMetadata: AES e({0}) keybits({1}) _LOH({2})", - FileName, keystrength, _LengthOfHeader); - - } -#endif - - } - - - - private void CopyThroughOneEntry(Stream outStream) - { - // Just read the entry from the existing input zipfile and write to the output. - // But, if metadata has changed (like file times or attributes), or if the ZIP64 - // option has changed, we can re-stream the entry data but must recompute the - // metadata. - if (this.LengthOfHeader == 0) - throw new BadStateException("Bad header length."); - - // is it necessary to re-constitute new metadata for this entry? - bool needRecompute = _metadataChanged || - (this.ArchiveStream is ZipSegmentedStream) || - (outStream is ZipSegmentedStream) || - (_InputUsesZip64 && _container.UseZip64WhenSaving == Zip64Option.Never) || - (!_InputUsesZip64 && _container.UseZip64WhenSaving == Zip64Option.Always); - - if (needRecompute) - CopyThroughWithRecompute(outStream); - else - CopyThroughWithNoChange(outStream); - - // zip64 housekeeping - _entryRequiresZip64 = new Nullable - (_CompressedSize >= 0xFFFFFFFF || _UncompressedSize >= 0xFFFFFFFF || - _RelativeOffsetOfLocalHeader >= 0xFFFFFFFF - ); - - _OutputUsesZip64 = new Nullable(_container.Zip64 == Zip64Option.Always || _entryRequiresZip64.Value); - } - - - - private void CopyThroughWithRecompute(Stream outstream) - { - int n; - byte[] bytes = new byte[BufferSize]; - var input = new CountingStream(this.ArchiveStream); - - long origRelativeOffsetOfHeader = _RelativeOffsetOfLocalHeader; - - // The header length may change due to rename of file, add a comment, etc. - // We need to retain the original. - int origLengthOfHeader = LengthOfHeader; // including crypto bytes! - - // WriteHeader() has the side effect of changing _RelativeOffsetOfLocalHeader - // and setting _LengthOfHeader. While ReadHeader() reads the crypto header if - // present, WriteHeader() does not write the crypto header. - WriteHeader(outstream, 0); - StoreRelativeOffset(); - - if (!this.FileName.EndsWith("/")) - { - // Not a directory; there is file data. - // Seek to the beginning of the entry data in the input stream. - - long pos = origRelativeOffsetOfHeader + origLengthOfHeader; - int len = GetLengthOfCryptoHeaderBytes(_Encryption_FromZipFile); - pos -= len; // want to keep the crypto header - _LengthOfHeader += len; - - input.Seek(pos, SeekOrigin.Begin); - - // copy through everything after the header to the output stream - long remaining = this._CompressedSize; - - while (remaining > 0) - { - len = (remaining > bytes.Length) ? bytes.Length : (int)remaining; - - // read - n = input.Read(bytes, 0, len); - //_CheckRead(n); - - // write - outstream.Write(bytes, 0, n); - remaining -= n; - OnWriteBlock(input.BytesRead, this._CompressedSize); - if (_ioOperationCanceled) - break; - } - - // bit 3 descriptor - if ((this._BitField & 0x0008) == 0x0008) - { - int size = 16; - if (_InputUsesZip64) size += 8; - byte[] Descriptor = new byte[size]; - input.Read(Descriptor, 0, size); - - if (_InputUsesZip64 && _container.UseZip64WhenSaving == Zip64Option.Never) - { - // original descriptor was 24 bytes, now we need 16. - // Must check for underflow here. - // signature + CRC. - outstream.Write(Descriptor, 0, 8); - - // Compressed - if (_CompressedSize > 0xFFFFFFFF) - throw new InvalidOperationException("ZIP64 is required"); - outstream.Write(Descriptor, 8, 4); - - // UnCompressed - if (_UncompressedSize > 0xFFFFFFFF) - throw new InvalidOperationException("ZIP64 is required"); - outstream.Write(Descriptor, 16, 4); - _LengthOfTrailer -= 8; - } - else if (!_InputUsesZip64 && _container.UseZip64WhenSaving == Zip64Option.Always) - { - // original descriptor was 16 bytes, now we need 24 - // signature + CRC - byte[] pad = new byte[4]; - outstream.Write(Descriptor, 0, 8); - // Compressed - outstream.Write(Descriptor, 8, 4); - outstream.Write(pad, 0, 4); - // UnCompressed - outstream.Write(Descriptor, 12, 4); - outstream.Write(pad, 0, 4); - _LengthOfTrailer += 8; - } - else - { - // same descriptor on input and output. Copy it through. - outstream.Write(Descriptor, 0, size); - //_LengthOfTrailer += size; - } - } - } - - _TotalEntrySize = _LengthOfHeader + _CompressedFileDataSize + _LengthOfTrailer; - } - - - private void CopyThroughWithNoChange(Stream outstream) - { - int n; - byte[] bytes = new byte[BufferSize]; - var input = new CountingStream(this.ArchiveStream); - - // seek to the beginning of the entry data in the input stream - input.Seek(this._RelativeOffsetOfLocalHeader, SeekOrigin.Begin); - - if (this._TotalEntrySize == 0) - { - // We've never set the length of the entry. - // Set it here. - this._TotalEntrySize = this._LengthOfHeader + this._CompressedFileDataSize + _LengthOfTrailer; - - // The CompressedSize includes all the leading metadata associated - // to encryption, if any, as well as the compressed data, or - // compressed-then-encrypted data, and the trailer in case of AES. - - // The CompressedFileData size is the same, less the encryption - // framing data (12 bytes header for PKZip; 10/18 bytes header and - // 10 byte trailer for AES). - - // The _LengthOfHeader includes all the zip entry header plus the - // crypto header, if any. The _LengthOfTrailer includes the - // 10-byte MAC for AES, where appropriate, and the bit-3 - // Descriptor, where applicable. - } - - - // workitem 5616 - // remember the offset, within the output stream, of this particular entry header. - // This may have changed if any of the other entries changed (eg, if a different - // entry was removed or added.) - var counter = outstream as CountingStream; - _RelativeOffsetOfLocalHeader = (counter != null) - ? counter.ComputedPosition - : outstream.Position; // BytesWritten - - // copy through the header, filedata, trailer, everything... - long remaining = this._TotalEntrySize; - while (remaining > 0) - { - int len = (remaining > bytes.Length) ? bytes.Length : (int)remaining; - - // read - n = input.Read(bytes, 0, len); - //_CheckRead(n); - - // write - outstream.Write(bytes, 0, n); - remaining -= n; - OnWriteBlock(input.BytesRead, this._TotalEntrySize); - if (_ioOperationCanceled) - break; - } - } - - - - - [System.Diagnostics.ConditionalAttribute("Trace")] - private void TraceWriteLine(string format, params object[] varParams) - { - lock (_outputLock) - { - int tid = System.Threading.Thread.CurrentThread.GetHashCode(); -#if ! (NETCF || SILVERLIGHT) - Console.ForegroundColor = (ConsoleColor)(tid % 8 + 8); -#endif - Console.Write("{0:000} ZipEntry.Write ", tid); - Console.WriteLine(format, varParams); -#if ! (NETCF || SILVERLIGHT) - Console.ResetColor(); -#endif - } - } - - private object _outputLock = new Object(); - } -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntry.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntry.cs deleted file mode 100644 index 02d3f5b7..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntry.cs +++ /dev/null @@ -1,2968 +0,0 @@ -// ZipEntry.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2006-2010 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-August-06 17:25:53> -// -// ------------------------------------------------------------------ -// -// This module defines the ZipEntry class, which models the entries within a zip file. -// -// Created: Tue, 27 Mar 2007 15:30 -// -// ------------------------------------------------------------------ - - -using System; -using System.IO; -using Interop = System.Runtime.InteropServices; - -namespace Ionic.Zip -{ - /// - /// Represents a single entry in a ZipFile. Typically, applications get a ZipEntry - /// by enumerating the entries within a ZipFile, or by adding an entry to a ZipFile. - /// - - [Interop.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d00004")] - [Interop.ComVisible(true)] -#if !NETCF - [Interop.ClassInterface(Interop.ClassInterfaceType.AutoDispatch)] // AutoDual -#endif - public partial class ZipEntry - { - /// - /// Default constructor. - /// - /// - /// Applications should never need to call this directly. It is exposed to - /// support COM Automation environments. - /// - public ZipEntry() - { - _CompressionMethod = (Int16)CompressionMethod.Deflate; - _CompressionLevel = Ionic.Zlib.CompressionLevel.Default; - _Encryption = EncryptionAlgorithm.None; - _Source = ZipEntrySource.None; - AlternateEncoding = System.Text.Encoding.GetEncoding("IBM437"); - AlternateEncodingUsage = ZipOption.Never; - } - - /// - /// The time and date at which the file indicated by the ZipEntry was - /// last modified. - /// - /// - /// - /// - /// The DotNetZip library sets the LastModified value for an entry, equal to - /// the Last Modified time of the file in the filesystem. If an entry is - /// added from a stream, the library uses System.DateTime.Now for this - /// value, for the given entry. - /// - /// - /// - /// This property allows the application to retrieve and possibly set the - /// LastModified value on an entry, to an arbitrary value. values with a - /// setting of DateTimeKind.Unspecified are taken to be expressed as - /// DateTimeKind.Local. - /// - /// - /// - /// Be aware that because of the way PKWare's - /// Zip specification describes how times are stored in the zip file, - /// the full precision of the System.DateTime datatype is not stored - /// for the last modified time when saving zip files. For more information on - /// how times are formatted, see the PKZip specification. - /// - /// - /// - /// The actual last modified time of a file can be stored in multiple ways in - /// the zip file, and they are not mutually exclusive: - /// - /// - /// - /// - /// In the so-called "DOS" format, which has a 2-second precision. Values - /// are rounded to the nearest even second. For example, if the time on the - /// file is 12:34:43, then it will be stored as 12:34:44. This first value - /// is accessible via the LastModified property. This value is always - /// present in the metadata for each zip entry. In some cases the value is - /// invalid, or zero. - /// - /// - /// - /// In the so-called "Windows" or "NTFS" format, as an 8-byte integer - /// quantity expressed as the number of 1/10 milliseconds (in other words - /// the number of 100 nanosecond units) since January 1, 1601 (UTC). This - /// format is how Windows represents file times. This time is accessible - /// via the ModifiedTime property. - /// - /// - /// - /// In the "Unix" format, a 4-byte quantity specifying the number of seconds since - /// January 1, 1970 UTC. - /// - /// - /// - /// In an older format, now deprecated but still used by some current - /// tools. This format is also a 4-byte quantity specifying the number of - /// seconds since January 1, 1970 UTC. - /// - /// - /// - /// - /// - /// Zip tools and libraries will always at least handle (read or write) the - /// DOS time, and may also handle the other time formats. Keep in mind that - /// while the names refer to particular operating systems, there is nothing in - /// the time formats themselves that prevents their use on other operating - /// systems. - /// - /// - /// - /// When reading ZIP files, the DotNetZip library reads the Windows-formatted - /// time, if it is stored in the entry, and sets both LastModified and - /// ModifiedTime to that value. When writing ZIP files, the DotNetZip - /// library by default will write both time quantities. It can also emit the - /// Unix-formatted time if desired (See .) - /// - /// - /// - /// The last modified time of the file created upon a call to - /// ZipEntry.Extract() may be adjusted during extraction to compensate - /// for differences in how the .NET Base Class Library deals with daylight - /// saving time (DST) versus how the Windows filesystem deals with daylight - /// saving time. Raymond Chen provides - /// some good context. - /// - /// - /// - /// In a nutshell: Daylight savings time rules change regularly. In 2007, for - /// example, the inception week of DST changed. In 1977, DST was in place all - /// year round. In 1945, likewise. And so on. Win32 does not attempt to - /// guess which time zone rules were in effect at the time in question. It - /// will render a time as "standard time" and allow the app to change to DST - /// as necessary. .NET makes a different choice. - /// - /// - /// - /// Compare the output of FileInfo.LastWriteTime.ToString("f") with what you - /// see in the Windows Explorer property sheet for a file that was last - /// written to on the other side of the DST transition. For example, suppose - /// the file was last modified on October 17, 2003, during DST but DST is not - /// currently in effect. Explorer's file properties reports Thursday, October - /// 17, 2003, 8:45:38 AM, but .NETs FileInfo reports Thursday, October 17, - /// 2003, 9:45 AM. - /// - /// - /// - /// Win32 says, "Thursday, October 17, 2002 8:45:38 AM PST". Note: Pacific - /// STANDARD Time. Even though October 17 of that year occurred during Pacific - /// Daylight Time, Win32 displays the time as standard time because that's - /// what time it is NOW. - /// - /// - /// - /// .NET BCL assumes that the current DST rules were in place at the time in - /// question. So, .NET says, "Well, if the rules in effect now were also in - /// effect on October 17, 2003, then that would be daylight time" so it - /// displays "Thursday, October 17, 2003, 9:45 AM PDT" - daylight time. - /// - /// - /// - /// So .NET gives a value which is more intuitively correct, but is also - /// potentially incorrect, and which is not invertible. Win32 gives a value - /// which is intuitively incorrect, but is strictly correct. - /// - /// - /// - /// Because of this funkiness, this library adds one hour to the LastModified - /// time on the extracted file, if necessary. That is to say, if the time in - /// question had occurred in what the .NET Base Class Library assumed to be - /// DST. This assumption may be wrong given the constantly changing DST rules, - /// but it is the best we can do. - /// - /// - /// - /// - public DateTime LastModified - { - get { return _LastModified.ToLocalTime(); } - set - { - _LastModified = (value.Kind == DateTimeKind.Unspecified) - ? DateTime.SpecifyKind(value, DateTimeKind.Local) - : value.ToLocalTime(); - _Mtime = Ionic.Zip.SharedUtilities.AdjustTime_Reverse(_LastModified).ToUniversalTime(); - _metadataChanged = true; - } - } - - - private int BufferSize - { - get - { - return this._container.BufferSize; - } - } - - /// - /// Last Modified time for the file represented by the entry. - /// - /// - /// - /// - /// - /// This value corresponds to the "last modified" time in the NTFS file times - /// as described in the Zip - /// specification. When getting this property, the value may be - /// different from . When setting the property, - /// the property also gets set, but with a lower - /// precision. - /// - /// - /// - /// Let me explain. It's going to take a while, so get - /// comfortable. Originally, waaaaay back in 1989 when the ZIP specification - /// was originally described by the esteemed Mr. Phil Katz, the dominant - /// operating system of the time was MS-DOS. MSDOS stored file times with a - /// 2-second precision, because, c'mon, who is ever going to need better - /// resolution than THAT? And so ZIP files, regardless of the platform on - /// which the zip file was created, store file times in exactly the same format that DOS used - /// in 1989. - /// - /// - /// - /// Since then, the ZIP spec has evolved, but the internal format for file - /// timestamps remains the same. Despite the fact that the way times are - /// stored in a zip file is rooted in DOS heritage, any program on any - /// operating system can format a time in this way, and most zip tools and - /// libraries DO - they round file times to the nearest even second and store - /// it just like DOS did 25+ years ago. - /// - /// - /// - /// PKWare extended the ZIP specification to allow a zip file to store what - /// are called "NTFS Times" and "Unix(tm) times" for a file. These are the - /// last write, last access, and file creation - /// times of a particular file. These metadata are not actually specific - /// to NTFS or Unix. They are tracked for each file by NTFS and by various - /// Unix filesystems, but they are also tracked by other filesystems, too. - /// The key point is that the times are formatted in the zip file - /// in the same way that NTFS formats the time (ticks since win32 epoch), - /// or in the same way that Unix formats the time (seconds since Unix - /// epoch). As with the DOS time, any tool or library running on any - /// operating system is capable of formatting a time in one of these ways - /// and embedding it into the zip file. - /// - /// - /// - /// These extended times are higher precision quantities than the DOS time. - /// As described above, the (DOS) LastModified has a precision of 2 seconds. - /// The Unix time is stored with a precision of 1 second. The NTFS time is - /// stored with a precision of 0.0000001 seconds. The quantities are easily - /// convertible, except for the loss of precision you may incur. - /// - /// - /// - /// A zip archive can store the {C,A,M} times in NTFS format, in Unix format, - /// or not at all. Often a tool running on Unix or Mac will embed the times - /// in Unix format (1 second precision), while WinZip running on Windows might - /// embed the times in NTFS format (precision of of 0.0000001 seconds). When - /// reading a zip file with these "extended" times, in either format, - /// DotNetZip represents the values with the - /// ModifiedTime, AccessedTime and CreationTime - /// properties on the ZipEntry. - /// - /// - /// - /// While any zip application or library, regardless of the platform it - /// runs on, could use any of the time formats allowed by the ZIP - /// specification, not all zip tools or libraries do support all these - /// formats. Storing the higher-precision times for each entry is - /// optional for zip files, and many tools and libraries don't use the - /// higher precision quantities at all. The old DOS time, represented by - /// , is guaranteed to be present, though it - /// sometimes unset. - /// - /// - /// - /// Ok, getting back to the question about how the LastModified - /// property relates to this ModifiedTime - /// property... LastModified is always set, while - /// ModifiedTime is not. (The other times stored in the NTFS - /// times extension, CreationTime and AccessedTime also - /// may not be set on an entry that is read from an existing zip file.) - /// When reading a zip file, then LastModified takes the DOS time - /// that is stored with the file. If the DOS time has been stored as zero - /// in the zipfile, then this library will use DateTime.Now for the - /// LastModified value. If the ZIP file was created by an evolved - /// tool, then there will also be higher precision NTFS or Unix times in - /// the zip file. In that case, this library will read those times, and - /// set LastModified and ModifiedTime to the same value, the - /// one corresponding to the last write time of the file. If there are no - /// higher precision times stored for the entry, then ModifiedTime - /// remains unset (likewise AccessedTime and CreationTime), - /// and LastModified keeps its DOS time. - /// - /// - /// - /// When creating zip files with this library, by default the extended time - /// properties (ModifiedTime, AccessedTime, and - /// CreationTime) are set on the ZipEntry instance, and these data are - /// stored in the zip archive for each entry, in NTFS format. If you add an - /// entry from an actual filesystem file, then the entry gets the actual file - /// times for that file, to NTFS-level precision. If you add an entry from a - /// stream, or a string, then the times get the value DateTime.Now. In - /// this case LastModified and ModifiedTime will be identical, - /// to 2 seconds of precision. You can explicitly set the - /// CreationTime, AccessedTime, and ModifiedTime of an - /// entry using the property setters. If you want to set all of those - /// quantities, it's more efficient to use the method. Those - /// changes are not made permanent in the zip file until you call or one of its cousins. - /// - /// - /// - /// When creating a zip file, you can override the default behavior of - /// this library for formatting times in the zip file, disabling the - /// embedding of file times in NTFS format or enabling the storage of file - /// times in Unix format, or both. You may want to do this, for example, - /// when creating a zip file on Windows, that will be consumed on a Mac, - /// by an application that is not hip to the "NTFS times" format. To do - /// this, use the and - /// properties. A valid zip - /// file may store the file times in both formats. But, there are no - /// guarantees that a program running on Mac or Linux will gracefully - /// handle the NTFS-formatted times when Unix times are present, or that a - /// non-DotNetZip-powered application running on Windows will be able to - /// handle file times in Unix format. DotNetZip will always do something - /// reasonable; other libraries or tools may not. When in doubt, test. - /// - /// - /// - /// I'll bet you didn't think one person could type so much about time, eh? - /// And reading it was so enjoyable, too! Well, in appreciation, maybe you - /// should donate? - /// - /// - /// - /// - /// - /// - /// - public DateTime ModifiedTime - { - get { return _Mtime; } - set - { - SetEntryTimes(_Ctime, _Atime, value); - } - } - - /// - /// Last Access time for the file represented by the entry. - /// - /// - /// This value may or may not be meaningful. If the ZipEntry was read from an existing - /// Zip archive, this information may not be available. For an explanation of why, see - /// . - /// - /// - /// - /// - public DateTime AccessedTime - { - get { return _Atime; } - set - { - SetEntryTimes(_Ctime, value, _Mtime); - } - } - - /// - /// The file creation time for the file represented by the entry. - /// - /// - /// - /// This value may or may not be meaningful. If the ZipEntry was read - /// from an existing zip archive, and the creation time was not set on the entry - /// when the zip file was created, then this property may be meaningless. For an - /// explanation of why, see . - /// - /// - /// - /// - public DateTime CreationTime - { - get { return _Ctime; } - set - { - SetEntryTimes(value, _Atime, _Mtime); - } - } - - /// - /// Sets the NTFS Creation, Access, and Modified times for the given entry. - /// - /// - /// - /// - /// When adding an entry from a file or directory, the Creation, Access, and - /// Modified times for the given entry are automatically set from the - /// filesystem values. When adding an entry from a stream or string, the - /// values are implicitly set to DateTime.Now. The application may wish to - /// set these values to some arbitrary value, before saving the archive, and - /// can do so using the various setters. If you want to set all of the times, - /// this method is more efficient. - /// - /// - /// - /// The values you set here will be retrievable with the , and properties. - /// - /// - /// - /// When this method is called, if both and are false, then the - /// EmitTimesInWindowsFormatWhenSaving flag is automatically set. - /// - /// - /// - /// DateTime values provided here without a DateTimeKind are assumed to be Local Time. - /// - /// - /// - /// the creation time of the entry. - /// the last access time of the entry. - /// the last modified time of the entry. - /// - /// - /// - /// - /// - /// - public void SetEntryTimes(DateTime created, DateTime accessed, DateTime modified) - { - _ntfsTimesAreSet = true; - if (created == _zeroHour && created.Kind == _zeroHour.Kind) created = _win32Epoch; - if (accessed == _zeroHour && accessed.Kind == _zeroHour.Kind) accessed = _win32Epoch; - if (modified == _zeroHour && modified.Kind == _zeroHour.Kind) modified = _win32Epoch; - _Ctime = created.ToUniversalTime(); - _Atime = accessed.ToUniversalTime(); - _Mtime = modified.ToUniversalTime(); - _LastModified = _Mtime; - if (!_emitUnixTimes && !_emitNtfsTimes) - _emitNtfsTimes = true; - _metadataChanged = true; - } - - - - /// - /// Specifies whether the Creation, Access, and Modified times for the given - /// entry will be emitted in "Windows format" when the zip archive is saved. - /// - /// - /// - /// - /// An application creating a zip archive can use this flag to explicitly - /// specify that the file times for the entry should or should not be stored - /// in the zip archive in the format used by Windows. The default value of - /// this property is true. - /// - /// - /// - /// When adding an entry from a file or directory, the Creation (), Access (), and Modified - /// () times for the given entry are automatically - /// set from the filesystem values. When adding an entry from a stream or - /// string, all three values are implicitly set to DateTime.Now. Applications - /// can also explicitly set those times by calling . - /// - /// - /// - /// PKWARE's - /// zip specification describes multiple ways to format these times in a - /// zip file. One is the format Windows applications normally use: 100ns ticks - /// since Jan 1, 1601 UTC. The other is a format Unix applications typically - /// use: seconds since January 1, 1970 UTC. Each format can be stored in an - /// "extra field" in the zip entry when saving the zip archive. The former - /// uses an extra field with a Header Id of 0x000A, while the latter uses a - /// header ID of 0x5455. - /// - /// - /// - /// Not all zip tools and libraries can interpret these fields. Windows - /// compressed folders is one that can read the Windows Format timestamps, - /// while I believe the Infozip - /// tools can read the Unix format timestamps. Although the time values are - /// easily convertible, subject to a loss of precision, some tools and - /// libraries may be able to read only one or the other. DotNetZip can read or - /// write times in either or both formats. - /// - /// - /// - /// The times stored are taken from , , and . - /// - /// - /// - /// This property is not mutually exclusive from the property. It is - /// possible that a zip entry can embed the timestamps in both forms, one - /// form, or neither. But, there are no guarantees that a program running on - /// Mac or Linux will gracefully handle NTFS Formatted times, or that a - /// non-DotNetZip-powered application running on Windows will be able to - /// handle file times in Unix format. When in doubt, test. - /// - /// - /// - /// Normally you will use the ZipFile.EmitTimesInWindowsFormatWhenSaving - /// property, to specify the behavior for all entries in a zip, rather than - /// the property on each individual entry. - /// - /// - /// - /// - /// - /// - /// - /// - /// - public bool EmitTimesInWindowsFormatWhenSaving - { - get - { - return _emitNtfsTimes; - } - set - { - _emitNtfsTimes = value; - _metadataChanged = true; - } - } - - /// - /// Specifies whether the Creation, Access, and Modified times for the given - /// entry will be emitted in "Unix(tm) format" when the zip archive is saved. - /// - /// - /// - /// - /// An application creating a zip archive can use this flag to explicitly - /// specify that the file times for the entry should or should not be stored - /// in the zip archive in the format used by Unix. By default this flag is - /// false, meaning the Unix-format times are not stored in the zip - /// archive. - /// - /// - /// - /// When adding an entry from a file or directory, the Creation (), Access (), and Modified - /// () times for the given entry are automatically - /// set from the filesystem values. When adding an entry from a stream or - /// string, all three values are implicitly set to DateTime.Now. Applications - /// can also explicitly set those times by calling . - /// - /// - /// - /// PKWARE's - /// zip specification describes multiple ways to format these times in a - /// zip file. One is the format Windows applications normally use: 100ns ticks - /// since Jan 1, 1601 UTC. The other is a format Unix applications typically - /// use: seconds since Jan 1, 1970 UTC. Each format can be stored in an - /// "extra field" in the zip entry when saving the zip archive. The former - /// uses an extra field with a Header Id of 0x000A, while the latter uses a - /// header ID of 0x5455. - /// - /// - /// - /// Not all tools and libraries can interpret these fields. Windows - /// compressed folders is one that can read the Windows Format timestamps, - /// while I believe the Infozip - /// tools can read the Unix format timestamps. Although the time values are - /// easily convertible, subject to a loss of precision, some tools and - /// libraries may be able to read only one or the other. DotNetZip can read or - /// write times in either or both formats. - /// - /// - /// - /// The times stored are taken from , , and . - /// - /// - /// - /// This property is not mutually exclusive from the property. It is - /// possible that a zip entry can embed the timestamps in both forms, one - /// form, or neither. But, there are no guarantees that a program running on - /// Mac or Linux will gracefully handle NTFS Formatted times, or that a - /// non-DotNetZip-powered application running on Windows will be able to - /// handle file times in Unix format. When in doubt, test. - /// - /// - /// - /// Normally you will use the ZipFile.EmitTimesInUnixFormatWhenSaving - /// property, to specify the behavior for all entries, rather than the - /// property on each individual entry. - /// - /// - /// - /// - /// - /// - /// - /// - /// - public bool EmitTimesInUnixFormatWhenSaving - { - get - { - return _emitUnixTimes; - } - set - { - _emitUnixTimes = value; - _metadataChanged = true; - } - } - - - /// - /// The type of timestamp attached to the ZipEntry. - /// - /// - /// - /// This property is valid only for a ZipEntry that was read from a zip archive. - /// It indicates the type of timestamp attached to the entry. - /// - /// - /// - /// - public ZipEntryTimestamp Timestamp - { - get - { - return _timestamp; - } - } - - /// - /// The file attributes for the entry. - /// - /// - /// - /// - /// - /// The attributes in NTFS include - /// ReadOnly, Archive, Hidden, System, and Indexed. When adding a - /// ZipEntry to a ZipFile, these attributes are set implicitly when - /// adding an entry from the filesystem. When adding an entry from a stream - /// or string, the Attributes are not set implicitly. Regardless of the way - /// an entry was added to a ZipFile, you can set the attributes - /// explicitly if you like. - /// - /// - /// - /// When reading a ZipEntry from a ZipFile, the attributes are - /// set according to the data stored in the ZipFile. If you extract the - /// entry from the archive to a filesystem file, DotNetZip will set the - /// attributes on the resulting file accordingly. - /// - /// - /// - /// The attributes can be set explicitly by the application. For example the - /// application may wish to set the FileAttributes.ReadOnly bit for all - /// entries added to an archive, so that on unpack, this attribute will be set - /// on the extracted file. Any changes you make to this property are made - /// permanent only when you call a Save() method on the ZipFile - /// instance that contains the ZipEntry. - /// - /// - /// - /// For example, an application may wish to zip up a directory and set the - /// ReadOnly bit on every file in the archive, so that upon later extraction, - /// the resulting files will be marked as ReadOnly. Not every extraction tool - /// respects these attributes, but if you unpack with DotNetZip, as for - /// example in a self-extracting archive, then the attributes will be set as - /// they are stored in the ZipFile. - /// - /// - /// - /// These attributes may not be interesting or useful if the resulting archive - /// is extracted on a non-Windows platform. How these attributes get used - /// upon extraction depends on the platform and tool used. - /// - /// - /// - /// This property is only partially supported in the Silverlight version - /// of the library: applications can read attributes on entries within - /// ZipFiles. But extracting entries within Silverlight will not set the - /// attributes on the extracted files. - /// - /// - /// - public System.IO.FileAttributes Attributes - { - // workitem 7071 - get { return (System.IO.FileAttributes)_ExternalFileAttrs; } - set - { - _ExternalFileAttrs = (int)value; - // Since the application is explicitly setting the attributes, overwriting - // whatever was there, we will explicitly set the Version made by field. - // workitem 7926 - "version made by" OS should be zero for compat with WinZip - _VersionMadeBy = (0 << 8) + 45; // v4.5 of the spec - _metadataChanged = true; - } - } - - - /// - /// The name of the filesystem file, referred to by the ZipEntry. - /// - /// - /// - /// - /// This property specifies the thing-to-be-zipped on disk, and is set only - /// when the ZipEntry is being created from a filesystem file. If the - /// ZipFile is instantiated by reading an existing .zip archive, then - /// the LocalFileName will be null (Nothing in VB). - /// - /// - /// - /// When it is set, the value of this property may be different than , which is the path used in the archive itself. If you - /// call Zip.AddFile("foop.txt", AlternativeDirectory), then the path - /// used for the ZipEntry within the zip archive will be different - /// than this path. - /// - /// - /// - /// If the entry is being added from a stream, then this is null (Nothing in VB). - /// - /// - /// - /// - internal string LocalFileName - { - get { return _LocalFileName; } - } - - /// - /// The name of the file contained in the ZipEntry. - /// - /// - /// - /// - /// - /// This is the name of the entry in the ZipFile itself. When creating - /// a zip archive, if the ZipEntry has been created from a filesystem - /// file, via a call to or , or a related overload, the value - /// of this property is derived from the name of that file. The - /// FileName property does not include drive letters, and may include a - /// different directory path, depending on the value of the - /// directoryPathInArchive parameter used when adding the entry into - /// the ZipFile. - /// - /// - /// - /// In some cases there is no related filesystem file - for example when a - /// ZipEntry is created using or one of the similar overloads. In this case, the value of - /// this property is derived from the fileName and the directory path passed - /// to that method. - /// - /// - /// - /// When reading a zip file, this property takes the value of the entry name - /// as stored in the zip file. If you extract such an entry, the extracted - /// file will take the name given by this property. - /// - /// - /// - /// Applications can set this property when creating new zip archives or when - /// reading existing archives. When setting this property, the actual value - /// that is set will replace backslashes with forward slashes, in accordance - /// with the Zip - /// specification, for compatibility with Unix(tm) and ... get - /// this.... Amiga! - /// - /// - /// - /// If an application reads a ZipFile via or a related overload, and then explicitly - /// sets the FileName on an entry contained within the ZipFile, and - /// then calls , the application will effectively - /// rename the entry within the zip archive. - /// - /// - /// - /// If an application sets the value of FileName, then calls - /// Extract() on the entry, the entry is extracted to a file using the - /// newly set value as the filename. The FileName value is made - /// permanent in the zip archive only after a call to one of the - /// ZipFile.Save() methods on the ZipFile that contains the - /// ZipEntry. - /// - /// - /// - /// If an application attempts to set the FileName to a value that - /// would result in a duplicate entry in the ZipFile, an exception is - /// thrown. - /// - /// - /// - /// When a ZipEntry is contained within a ZipFile, applications - /// cannot rename the entry within the context of a foreach (For - /// Each in VB) loop, because of the way the ZipFile stores - /// entries. If you need to enumerate through all the entries and rename one - /// or more of them, use ZipFile.EntriesSorted as the - /// collection. See also, ZipFile.GetEnumerator(). - /// - /// - /// - public string FileName - { - get { return _FileNameInArchive; } - set - { - if (_container.ZipFile == null) - throw new ZipException("Cannot rename; this is not supported in ZipOutputStream/ZipInputStream."); - - // rename the entry! - if (String.IsNullOrEmpty(value)) throw new ZipException("The FileName must be non empty and non-null."); - - var filename = ZipEntry.NameInArchive(value, null); - // workitem 8180 - if (_FileNameInArchive == filename) return; // nothing to do - - // workitem 8047 - when renaming, must remove old and then add a new entry - this._container.ZipFile.RemoveEntry(this); - this._container.ZipFile.InternalAddEntry(filename, this); - - _FileNameInArchive = filename; - _container.ZipFile.NotifyEntryChanged(); - _metadataChanged = true; - } - } - - - /// - /// The stream that provides content for the ZipEntry. - /// - /// - /// - /// - /// - /// The application can use this property to set the input stream for an - /// entry on a just-in-time basis. Imagine a scenario where the application - /// creates a ZipFile comprised of content obtained from hundreds of - /// files, via calls to AddFile(). The DotNetZip library opens streams - /// on these files on a just-in-time basis, only when writing the entry out to - /// an external store within the scope of a ZipFile.Save() call. Only - /// one input stream is opened at a time, as each entry is being written out. - /// - /// - /// - /// Now imagine a different application that creates a ZipFile - /// with content obtained from hundreds of streams, added through . Normally the - /// application would supply an open stream to that call. But when large - /// numbers of streams are being added, this can mean many open streams at one - /// time, unnecessarily. - /// - /// - /// - /// To avoid this, call and specify delegates that open and close the stream at - /// the time of Save. - /// - /// - /// - /// - /// Setting the value of this property when the entry was not added from a - /// stream (for example, when the ZipEntry was added with or , or when the entry was added by - /// reading an existing zip archive) will throw an exception. - /// - /// - /// - /// - public Stream InputStream - { - get { return _sourceStream; } - - set - { - if (this._Source != ZipEntrySource.Stream) - throw new ZipException("You must not set the input stream for this entry."); - - _sourceWasJitProvided = true; - _sourceStream = value; - } - } - - - /// - /// A flag indicating whether the InputStream was provided Just-in-time. - /// - /// - /// - /// - /// - /// When creating a zip archive, an application can obtain content for one or - /// more of the ZipEntry instances from streams, using the method. At the time - /// of calling that method, the application can supply null as the value of - /// the stream parameter. By doing so, the application indicates to the - /// library that it will provide a stream for the entry on a just-in-time - /// basis, at the time one of the ZipFile.Save() methods is called and - /// the data for the various entries are being compressed and written out. - /// - /// - /// - /// In this case, the application can set the - /// property, typically within the SaveProgress event (event type: ) for that entry. - /// - /// - /// - /// The application will later want to call Close() and Dispose() on that - /// stream. In the SaveProgress event, when the event type is , the application can - /// do so. This flag indicates that the stream has been provided by the - /// application on a just-in-time basis and that it is the application's - /// responsibility to call Close/Dispose on that stream. - /// - /// - /// - /// - public bool InputStreamWasJitProvided - { - get { return _sourceWasJitProvided; } - } - - - - /// - /// An enum indicating the source of the ZipEntry. - /// - public ZipEntrySource Source - { - get { return _Source; } - } - - - /// - /// The version of the zip engine needed to read the ZipEntry. - /// - /// - /// - /// - /// This is a readonly property, indicating the version of the Zip - /// specification that the extracting tool or library must support to - /// extract the given entry. Generally higher versions indicate newer - /// features. Older zip engines obviously won't know about new features, and - /// won't be able to extract entries that depend on those newer features. - /// - /// - /// - /// - /// value - /// Features - /// - /// - /// - /// 20 - /// a basic Zip Entry, potentially using PKZIP encryption. - /// - /// - /// - /// - /// 45 - /// The ZIP64 extension is used on the entry. - /// - /// - /// - /// - /// 46 - /// File is compressed using BZIP2 compression* - /// - /// - /// - /// 50 - /// File is encrypted using PkWare's DES, 3DES, (broken) RC2 or RC4 - /// - /// - /// - /// 51 - /// File is encrypted using PKWare's AES encryption or corrected RC2 encryption. - /// - /// - /// - /// 52 - /// File is encrypted using corrected RC2-64 encryption** - /// - /// - /// - /// 61 - /// File is encrypted using non-OAEP key wrapping*** - /// - /// - /// - /// 63 - /// File is compressed using LZMA, PPMd+, Blowfish, or Twofish - /// - /// - /// - /// - /// - /// There are other values possible, not listed here. DotNetZip supports - /// regular PKZip encryption, and ZIP64 extensions. DotNetZip cannot extract - /// entries that require a zip engine higher than 45. - /// - /// - /// - /// This value is set upon reading an existing zip file, or after saving a zip - /// archive. - /// - /// - public Int16 VersionNeeded - { - get { return _VersionNeeded; } - } - - /// - /// The comment attached to the ZipEntry. - /// - /// - /// - /// - /// Each entry in a zip file can optionally have a comment associated to - /// it. The comment might be displayed by a zip tool during extraction, for - /// example. - /// - /// - /// - /// By default, the Comment is encoded in IBM437 code page. You can - /// specify an alternative with and - /// . - /// - /// - /// - /// - public string Comment - { - get { return _Comment; } - set - { - _Comment = value; - _metadataChanged = true; - } - } - - - /// - /// Indicates whether the entry requires ZIP64 extensions. - /// - /// - /// - /// - /// - /// This property is null (Nothing in VB) until a Save() method on the - /// containing instance has been called. The property is - /// non-null (HasValue is true) only after a Save() method has - /// been called. - /// - /// - /// - /// After the containing ZipFile has been saved, the Value of this - /// property is true if any of the following three conditions holds: the - /// uncompressed size of the entry is larger than 0xFFFFFFFF; the compressed - /// size of the entry is larger than 0xFFFFFFFF; the relative offset of the - /// entry within the zip archive is larger than 0xFFFFFFFF. These quantities - /// are not known until a Save() is attempted on the zip archive and - /// the compression is applied. - /// - /// - /// - /// If none of the three conditions holds, then the Value is false. - /// - /// - /// - /// A Value of false does not indicate that the entry, as saved in the - /// zip archive, does not use ZIP64. It merely indicates that ZIP64 is - /// not required. An entry may use ZIP64 even when not required if - /// the property on the containing - /// ZipFile instance is set to , or if - /// the property on the containing - /// ZipFile instance is set to - /// and the output stream was not seekable. - /// - /// - /// - /// - public Nullable RequiresZip64 - { - get - { - return _entryRequiresZip64; - } - } - - /// - /// Indicates whether the entry actually used ZIP64 extensions, as it was most - /// recently written to the output file or stream. - /// - /// - /// - /// - /// - /// This Nullable property is null (Nothing in VB) until a Save() - /// method on the containing instance has been - /// called. HasValue is true only after a Save() method has been - /// called. - /// - /// - /// - /// The value of this property for a particular ZipEntry may change - /// over successive calls to Save() methods on the containing ZipFile, - /// even if the file that corresponds to the ZipEntry does not. This - /// may happen if other entries contained in the ZipFile expand, - /// causing the offset for this particular entry to exceed 0xFFFFFFFF. - /// - /// - /// - public Nullable OutputUsedZip64 - { - get { return _OutputUsesZip64; } - } - - - /// - /// The bitfield for the entry as defined in the zip spec. You probably - /// never need to look at this. - /// - /// - /// - /// - /// You probably do not need to concern yourself with the contents of this - /// property, but in case you do: - /// - /// - /// - /// - /// bit - /// meaning - /// - /// - /// - /// 0 - /// set if encryption is used. - /// - /// - /// - /// 1-2 - /// - /// set to determine whether normal, max, fast deflation. DotNetZip library - /// always leaves these bits unset when writing (indicating "normal" - /// deflation"), but can read an entry with any value here. - /// - /// - /// - /// - /// 3 - /// - /// Indicates that the Crc32, Compressed and Uncompressed sizes are zero in the - /// local header. This bit gets set on an entry during writing a zip file, when - /// it is saved to a non-seekable output stream. - /// - /// - /// - /// - /// - /// 4 - /// reserved for "enhanced deflating". This library doesn't do enhanced deflating. - /// - /// - /// - /// 5 - /// set to indicate the zip is compressed patched data. This library doesn't do that. - /// - /// - /// - /// 6 - /// - /// set if PKWare's strong encryption is used (must also set bit 1 if bit 6 is - /// set). This bit is not set if WinZip's AES encryption is set. - /// - /// - /// - /// 7 - /// not used - /// - /// - /// - /// 8 - /// not used - /// - /// - /// - /// 9 - /// not used - /// - /// - /// - /// 10 - /// not used - /// - /// - /// - /// 11 - /// - /// Language encoding flag (EFS). If this bit is set, the filename and comment - /// fields for this file must be encoded using UTF-8. This library currently - /// does not support UTF-8. - /// - /// - /// - /// - /// 12 - /// Reserved by PKWARE for enhanced compression. - /// - /// - /// - /// 13 - /// - /// Used when encrypting the Central Directory to indicate selected data - /// values in the Local Header are masked to hide their actual values. See - /// the section in the Zip - /// specification describing the Strong Encryption Specification for - /// details. - /// - /// - /// - /// - /// 14 - /// Reserved by PKWARE. - /// - /// - /// - /// 15 - /// Reserved by PKWARE. - /// - /// - /// - /// - /// - public Int16 BitField - { - get { return _BitField; } - } - - /// - /// The compression method employed for this ZipEntry. - /// - /// - /// - /// - /// - /// The - /// Zip specification allows a variety of compression methods. This - /// library supports just two: 0x08 = Deflate. 0x00 = Store (no compression), - /// for reading or writing. - /// - /// - /// - /// When reading an entry from an existing zipfile, the value you retrieve - /// here indicates the compression method used on the entry by the original - /// creator of the zip. When writing a zipfile, you can specify either 0x08 - /// (Deflate) or 0x00 (None). If you try setting something else, you will get - /// an exception. - /// - /// - /// - /// You may wish to set CompressionMethod to CompressionMethod.None (0) - /// when zipping already-compressed data like a jpg, png, or mp3 file. - /// This can save time and cpu cycles. - /// - /// - /// - /// When setting this property on a ZipEntry that is read from an - /// existing zip file, calling ZipFile.Save() will cause the new - /// CompressionMethod to be used on the entry in the newly saved zip file. - /// - /// - /// - /// Setting this property may have the side effect of modifying the - /// CompressionLevel property. If you set the CompressionMethod to a - /// value other than None, and CompressionLevel is previously - /// set to None, then CompressionLevel will be set to - /// Default. - /// - /// - /// - /// - /// - /// - /// In this example, the first entry added to the zip archive uses the default - /// behavior - compression is used where it makes sense. The second entry, - /// the MP3 file, is added to the archive without being compressed. - /// - /// using (ZipFile zip = new ZipFile(ZipFileToCreate)) - /// { - /// ZipEntry e1= zip.AddFile(@"notes\Readme.txt"); - /// ZipEntry e2= zip.AddFile(@"music\StopThisTrain.mp3"); - /// e2.CompressionMethod = CompressionMethod.None; - /// zip.Save(); - /// } - /// - /// - /// - /// Using zip As New ZipFile(ZipFileToCreate) - /// zip.AddFile("notes\Readme.txt") - /// Dim e2 as ZipEntry = zip.AddFile("music\StopThisTrain.mp3") - /// e2.CompressionMethod = CompressionMethod.None - /// zip.Save - /// End Using - /// - /// - public CompressionMethod CompressionMethod - { - get { return (CompressionMethod)_CompressionMethod; } - set - { - if (value == (CompressionMethod)_CompressionMethod) return; // nothing to do. - - if (value != CompressionMethod.None && value != CompressionMethod.Deflate -#if BZIP - && value != CompressionMethod.BZip2 -#endif - ) - throw new InvalidOperationException("Unsupported compression method."); - - // If the source is a zip archive and there was encryption on the - // entry, changing the compression method is not supported. - // if (this._Source == ZipEntrySource.ZipFile && _sourceIsEncrypted) - // throw new InvalidOperationException("Cannot change compression method on encrypted entries read from archives."); - - _CompressionMethod = (Int16)value; - - if (_CompressionMethod == (Int16)Ionic.Zip.CompressionMethod.None) - _CompressionLevel = Ionic.Zlib.CompressionLevel.None; - else if (CompressionLevel == Ionic.Zlib.CompressionLevel.None) - _CompressionLevel = Ionic.Zlib.CompressionLevel.Default; - - if (_container.ZipFile != null) _container.ZipFile.NotifyEntryChanged(); - _restreamRequiredOnSave = true; - } - } - - - /// - /// Sets the compression level to be used for the entry when saving the zip - /// archive. This applies only for CompressionMethod = DEFLATE. - /// - /// - /// - /// - /// When using the DEFLATE compression method, Varying the compression - /// level used on entries can affect the size-vs-speed tradeoff when - /// compression and decompressing data streams or files. - /// - /// - /// - /// If you do not set this property, the default compression level is used, - /// which normally gives a good balance of compression efficiency and - /// compression speed. In some tests, using BestCompression can - /// double the time it takes to compress, while delivering just a small - /// increase in compression efficiency. This behavior will vary with the - /// type of data you compress. If you are in doubt, just leave this setting - /// alone, and accept the default. - /// - /// - /// - /// When setting this property on a ZipEntry that is read from an - /// existing zip file, calling ZipFile.Save() will cause the new - /// CompressionLevel to be used on the entry in the newly saved zip file. - /// - /// - /// - /// Setting this property may have the side effect of modifying the - /// CompressionMethod property. If you set the CompressionLevel - /// to a value other than None, CompressionMethod will be set - /// to Deflate, if it was previously None. - /// - /// - /// - /// Setting this property has no effect if the CompressionMethod is something - /// other than Deflate or None. - /// - /// - /// - /// - public Ionic.Zlib.CompressionLevel CompressionLevel - { - get - { - return _CompressionLevel; - } - set - { - if (_CompressionMethod != (short)CompressionMethod.Deflate && - _CompressionMethod != (short)CompressionMethod.None) - return ; // no effect - - if (value == Ionic.Zlib.CompressionLevel.Default && - _CompressionMethod == (short)CompressionMethod.Deflate) return; // nothing to do - _CompressionLevel = value; - - if (value == Ionic.Zlib.CompressionLevel.None && - _CompressionMethod == (short)CompressionMethod.None) - return; // nothing more to do - - if (_CompressionLevel == Ionic.Zlib.CompressionLevel.None) - _CompressionMethod = (short) Ionic.Zip.CompressionMethod.None; - else - _CompressionMethod = (short) Ionic.Zip.CompressionMethod.Deflate; - - if (_container.ZipFile != null) _container.ZipFile.NotifyEntryChanged(); - _restreamRequiredOnSave = true; - } - } - - - - /// - /// The compressed size of the file, in bytes, within the zip archive. - /// - /// - /// - /// When reading a ZipFile, this value is read in from the existing - /// zip file. When creating or updating a ZipFile, the compressed - /// size is computed during compression. Therefore the value on a - /// ZipEntry is valid after a call to Save() (or one of its - /// overloads) in that case. - /// - /// - /// - public Int64 CompressedSize - { - get { return _CompressedSize; } - } - - /// - /// The size of the file, in bytes, before compression, or after extraction. - /// - /// - /// - /// When reading a ZipFile, this value is read in from the existing - /// zip file. When creating or updating a ZipFile, the uncompressed - /// size is computed during compression. Therefore the value on a - /// ZipEntry is valid after a call to Save() (or one of its - /// overloads) in that case. - /// - /// - /// - public Int64 UncompressedSize - { - get { return _UncompressedSize; } - } - - /// - /// The ratio of compressed size to uncompressed size of the ZipEntry. - /// - /// - /// - /// - /// This is a ratio of the compressed size to the uncompressed size of the - /// entry, expressed as a double in the range of 0 to 100+. A value of 100 - /// indicates no compression at all. It could be higher than 100 when the - /// compression algorithm actually inflates the data, as may occur for small - /// files, or uncompressible data that is encrypted. - /// - /// - /// - /// You could format it for presentation to a user via a format string of - /// "{3,5:F0}%" to see it as a percentage. - /// - /// - /// - /// If the size of the original uncompressed file is 0, implying a - /// denominator of 0, the return value will be zero. - /// - /// - /// - /// This property is valid after reading in an existing zip file, or after - /// saving the ZipFile that contains the ZipEntry. You cannot know the - /// effect of a compression transform until you try it. - /// - /// - /// - public Double CompressionRatio - { - get - { - if (UncompressedSize == 0) return 0; - return 100 * (1.0 - (1.0 * CompressedSize) / (1.0 * UncompressedSize)); - } - } - - /// - /// The 32-bit CRC (Cyclic Redundancy Check) on the contents of the ZipEntry. - /// - /// - /// - /// - /// You probably don't need to concern yourself with this. It is used - /// internally by DotNetZip to verify files or streams upon extraction. - /// - /// The value is a 32-bit - /// CRC using 0xEDB88320 for the polynomial. This is the same CRC-32 used in - /// PNG, MPEG-2, and other protocols and formats. It is a read-only property; when - /// creating a Zip archive, the CRC for each entry is set only after a call to - /// Save() on the containing ZipFile. When reading an existing zip file, the value - /// of this property reflects the stored CRC for the entry. - /// - /// - public Int32 Crc - { - get { return _Crc32; } - } - - /// - /// True if the entry is a directory (not a file). - /// This is a readonly property on the entry. - /// - public bool IsDirectory - { - get { return _IsDirectory; } - } - - /// - /// A derived property that is true if the entry uses encryption. - /// - /// - /// - /// - /// This is a readonly property on the entry. When reading a zip file, - /// the value for the ZipEntry is determined by the data read - /// from the zip file. After saving a ZipFile, the value of this - /// property for each ZipEntry indicates whether encryption was - /// actually used (which will have been true if the was set and the property - /// was something other than . - /// - /// - public bool UsesEncryption - { - get { return (_Encryption_FromZipFile != EncryptionAlgorithm.None); } - } - - - /// - /// Set this to specify which encryption algorithm to use for the entry when - /// saving it to a zip archive. - /// - /// - /// - /// - /// - /// Set this property in order to encrypt the entry when the ZipFile is - /// saved. When setting this property, you must also set a on the entry. If you set a value other than on this property and do not set a - /// Password then the entry will not be encrypted. The ZipEntry - /// data is encrypted as the ZipFile is saved, when you call or one of its cousins on the containing - /// ZipFile instance. You do not need to specify the Encryption - /// when extracting entries from an archive. - /// - /// - /// - /// The Zip specification from PKWare defines a set of encryption algorithms, - /// and the data formats for the zip archive that support them, and PKWare - /// supports those algorithms in the tools it produces. Other vendors of tools - /// and libraries, such as WinZip or Xceed, typically support a - /// subset of the algorithms specified by PKWare. These tools can - /// sometimes support additional different encryption algorithms and data - /// formats, not specified by PKWare. The AES Encryption specified and - /// supported by WinZip is the most popular example. This library supports a - /// subset of the complete set of algorithms specified by PKWare and other - /// vendors. - /// - /// - /// - /// There is no common, ubiquitous multi-vendor standard for strong encryption - /// within zip files. There is broad support for so-called "traditional" Zip - /// encryption, sometimes called Zip 2.0 encryption, as specified - /// by PKWare, but this encryption is considered weak and - /// breakable. This library currently supports the Zip 2.0 "weak" encryption, - /// and also a stronger WinZip-compatible AES encryption, using either 128-bit - /// or 256-bit key strength. If you want DotNetZip to support an algorithm - /// that is not currently supported, call the author of this library and maybe - /// we can talk business. - /// - /// - /// - /// The class also has a property. In most cases you will use - /// that property when setting encryption. This property takes - /// precedence over any Encryption set on the ZipFile itself. - /// Typically, you would use the per-entry Encryption when most entries in the - /// zip archive use one encryption algorithm, and a few entries use a - /// different one. If all entries in the zip file use the same Encryption, - /// then it is simpler to just set this property on the ZipFile itself, when - /// creating a zip archive. - /// - /// - /// - /// Some comments on updating archives: If you read a ZipFile, you can - /// modify the Encryption on an encrypted entry: you can remove encryption - /// from an entry that was encrypted; you can encrypt an entry that was not - /// encrypted previously; or, you can change the encryption algorithm. The - /// changes in encryption are not made permanent until you call Save() on the - /// ZipFile. To effect changes in encryption, the entry content is - /// streamed through several transformations, depending on the modification - /// the application has requested. For example if the entry is not encrypted - /// and the application sets Encryption to PkzipWeak, then at - /// the time of Save(), the original entry is read and decompressed, - /// then re-compressed and encrypted. Conversely, if the original entry is - /// encrypted with PkzipWeak encryption, and the application sets the - /// Encryption property to WinZipAes128, then at the time of - /// Save(), the original entry is decrypted via PKZIP encryption and - /// decompressed, then re-compressed and re-encrypted with AES. This all - /// happens automatically within the library, but it can be time-consuming for - /// large entries. - /// - /// - /// - /// Additionally, when updating archives, it is not possible to change the - /// password when changing the encryption algorithm. To change both the - /// algorithm and the password, you need to Save() the zipfile twice. First - /// set the Encryption to None, then call Save(). Then set the - /// Encryption to the new value (not "None"), then call Save() - /// once again. - /// - /// - /// - /// The WinZip AES encryption algorithms are not supported on the .NET Compact - /// Framework. - /// - /// - /// - /// - /// - /// This example creates a zip archive that uses encryption, and then extracts - /// entries from the archive. When creating the zip archive, the ReadMe.txt - /// file is zipped without using a password or encryption. The other file - /// uses encryption. - /// - /// - /// // Create a zip archive with AES Encryption. - /// using (ZipFile zip = new ZipFile()) - /// { - /// zip.AddFile("ReadMe.txt") - /// ZipEntry e1= zip.AddFile("2008-Regional-Sales-Report.pdf"); - /// e1.Encryption= EncryptionAlgorithm.WinZipAes256; - /// e1.Password= "Top.Secret.No.Peeking!"; - /// zip.Save("EncryptedArchive.zip"); - /// } - /// - /// // Extract a zip archive that uses AES Encryption. - /// // You do not need to specify the algorithm during extraction. - /// using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip")) - /// { - /// // Specify the password that is used during extraction, for - /// // all entries that require a password: - /// zip.Password= "Top.Secret.No.Peeking!"; - /// zip.ExtractAll("extractDirectory"); - /// } - /// - /// - /// - /// ' Create a zip that uses Encryption. - /// Using zip As New ZipFile() - /// zip.AddFile("ReadMe.txt") - /// Dim e1 as ZipEntry - /// e1= zip.AddFile("2008-Regional-Sales-Report.pdf") - /// e1.Encryption= EncryptionAlgorithm.WinZipAes256 - /// e1.Password= "Top.Secret.No.Peeking!" - /// zip.Save("EncryptedArchive.zip") - /// End Using - /// - /// ' Extract a zip archive that uses AES Encryption. - /// ' You do not need to specify the algorithm during extraction. - /// Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip")) - /// ' Specify the password that is used during extraction, for - /// ' all entries that require a password: - /// zip.Password= "Top.Secret.No.Peeking!" - /// zip.ExtractAll("extractDirectory") - /// End Using - /// - /// - /// - /// - /// - /// Thrown in the setter if EncryptionAlgorithm.Unsupported is specified. - /// - /// - /// ZipEntry.Password - /// ZipFile.Encryption - public EncryptionAlgorithm Encryption - { - get - { - return _Encryption; - } - set - { - if (value == _Encryption) return; // no change - - if (value == EncryptionAlgorithm.Unsupported) - throw new InvalidOperationException("You may not set Encryption to that value."); - - // If the source is a zip archive and there was encryption - // on the entry, this will not work. - //if (this._Source == ZipEntrySource.ZipFile && _sourceIsEncrypted) - // throw new InvalidOperationException("You cannot change the encryption method on encrypted entries read from archives."); - - _Encryption = value; - _restreamRequiredOnSave = true; - if (_container.ZipFile!=null) - _container.ZipFile.NotifyEntryChanged(); - } - } - - - /// - /// The Password to be used when encrypting a ZipEntry upon - /// ZipFile.Save(), or when decrypting an entry upon Extract(). - /// - /// - /// - /// - /// This is a write-only property on the entry. Set this to request that the - /// entry be encrypted when writing the zip archive, or set it to specify the - /// password to be used when extracting an existing entry that is encrypted. - /// - /// - /// - /// The password set here is implicitly used to encrypt the entry during the - /// operation, or to decrypt during the or operation. If you set - /// the Password on a ZipEntry after calling Save(), there is no - /// effect. - /// - /// - /// - /// Consider setting the property when using a - /// password. Answering concerns that the standard password protection - /// supported by all zip tools is weak, WinZip has extended the ZIP - /// specification with a way to use AES Encryption to protect entries in the - /// Zip file. Unlike the "PKZIP 2.0" encryption specified in the PKZIP - /// specification, AES - /// Encryption uses a standard, strong, tested, encryption - /// algorithm. DotNetZip can create zip archives that use WinZip-compatible - /// AES encryption, if you set the property. But, - /// archives created that use AES encryption may not be readable by all other - /// tools and libraries. For example, Windows Explorer cannot read a - /// "compressed folder" (a zip file) that uses AES encryption, though it can - /// read a zip file that uses "PKZIP encryption." - /// - /// - /// - /// The class also has a - /// property. This property takes precedence over any password set on the - /// ZipFile itself. Typically, you would use the per-entry Password when most - /// entries in the zip archive use one password, and a few entries use a - /// different password. If all entries in the zip file use the same password, - /// then it is simpler to just set this property on the ZipFile itself, - /// whether creating a zip archive or extracting a zip archive. - /// - /// - /// - /// Some comments on updating archives: If you read a ZipFile, you - /// cannot modify the password on any encrypted entry, except by extracting - /// the entry with the original password (if any), removing the original entry - /// via , and then adding a new - /// entry with a new Password. - /// - /// - /// - /// For example, suppose you read a ZipFile, and there is an encrypted - /// entry. Setting the Password property on that ZipEntry and then - /// calling Save() on the ZipFile does not update the password - /// on that entry in the archive. Neither is an exception thrown. Instead, - /// what happens during the Save() is the existing entry is copied - /// through to the new zip archive, in its original encrypted form. Upon - /// re-reading that archive, the entry can be decrypted with its original - /// password. - /// - /// - /// - /// If you read a ZipFile, and there is an un-encrypted entry, you can set the - /// Password on the entry and then call Save() on the ZipFile, and get - /// encryption on that entry. - /// - /// - /// - /// - /// - /// - /// This example creates a zip file with two entries, and then extracts the - /// entries from the zip file. When creating the zip file, the two files are - /// added to the zip file using password protection. Each entry uses a - /// different password. During extraction, each file is extracted with the - /// appropriate password. - /// - /// - /// // create a file with encryption - /// using (ZipFile zip = new ZipFile()) - /// { - /// ZipEntry entry; - /// entry= zip.AddFile("Declaration.txt"); - /// entry.Password= "123456!"; - /// entry = zip.AddFile("Report.xls"); - /// entry.Password= "1Secret!"; - /// zip.Save("EncryptedArchive.zip"); - /// } - /// - /// // extract entries that use encryption - /// using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip")) - /// { - /// ZipEntry entry; - /// entry = zip["Declaration.txt"]; - /// entry.Password = "123456!"; - /// entry.Extract("extractDir"); - /// entry = zip["Report.xls"]; - /// entry.Password = "1Secret!"; - /// entry.Extract("extractDir"); - /// } - /// - /// - /// - /// - /// Using zip As New ZipFile - /// Dim entry as ZipEntry - /// entry= zip.AddFile("Declaration.txt") - /// entry.Password= "123456!" - /// entry = zip.AddFile("Report.xls") - /// entry.Password= "1Secret!" - /// zip.Save("EncryptedArchive.zip") - /// End Using - /// - /// - /// ' extract entries that use encryption - /// Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip")) - /// Dim entry as ZipEntry - /// entry = zip("Declaration.txt") - /// entry.Password = "123456!" - /// entry.Extract("extractDir") - /// entry = zip("Report.xls") - /// entry.Password = "1Secret!" - /// entry.Extract("extractDir") - /// End Using - /// - /// - /// - /// - /// - /// - /// ZipFile.Password - public string Password - { - set - { - _Password = value; - if (_Password == null) - { - _Encryption = EncryptionAlgorithm.None; - } - else - { - // We're setting a non-null password. - - // For entries obtained from a zip file that are encrypted, we cannot - // simply restream (recompress, re-encrypt) the file data, because we - // need the old password in order to decrypt the data, and then we - // need the new password to encrypt. So, setting the password is - // never going to work on an entry that is stored encrypted in a zipfile. - - // But it is not en error to set the password, obviously: callers will - // set the password in order to Extract encrypted archives. - - // If the source is a zip archive and there was previously no encryption - // on the entry, then we must re-stream the entry in order to encrypt it. - if (this._Source == ZipEntrySource.ZipFile && !_sourceIsEncrypted) - _restreamRequiredOnSave = true; - - if (Encryption == EncryptionAlgorithm.None) - { - _Encryption = EncryptionAlgorithm.PkzipWeak; - } - } - } - private get { return _Password; } - } - - - - internal bool IsChanged - { - get - { - return _restreamRequiredOnSave | _metadataChanged; - } - } - - - /// - /// The action the library should take when extracting a file that already exists. - /// - /// - /// - /// - /// This property affects the behavior of the Extract methods (one of the - /// Extract() or ExtractWithPassword() overloads), when - /// extraction would would overwrite an existing filesystem file. If you do - /// not set this property, the library throws an exception when extracting - /// an entry would overwrite an existing file. - /// - /// - /// - /// This property has no effect when extracting to a stream, or when the file to be - /// extracted does not already exist. - /// - /// - /// - /// - /// - /// - /// This example shows how to set the ExtractExistingFile property in - /// an ExtractProgress event, in response to user input. The - /// ExtractProgress event is invoked if and only if the - /// ExtractExistingFile property was previously set to - /// ExtractExistingFileAction.InvokeExtractProgressEvent. - /// - /// public static void ExtractProgress(object sender, ExtractProgressEventArgs e) - /// { - /// if (e.EventType == ZipProgressEventType.Extracting_BeforeExtractEntry) - /// Console.WriteLine("extract {0} ", e.CurrentEntry.FileName); - /// - /// else if (e.EventType == ZipProgressEventType.Extracting_ExtractEntryWouldOverwrite) - /// { - /// ZipEntry entry = e.CurrentEntry; - /// string response = null; - /// // Ask the user if he wants overwrite the file - /// do - /// { - /// Console.Write("Overwrite {0} in {1} ? (y/n/C) ", entry.FileName, e.ExtractLocation); - /// response = Console.ReadLine(); - /// Console.WriteLine(); - /// - /// } while (response != null && response[0]!='Y' && - /// response[0]!='N' && response[0]!='C'); - /// - /// if (response[0]=='C') - /// e.Cancel = true; - /// else if (response[0]=='Y') - /// entry.ExtractExistingFile = ExtractExistingFileAction.OverwriteSilently; - /// else - /// entry.ExtractExistingFile= ExtractExistingFileAction.DoNotOverwrite; - /// } - /// } - /// - /// - public ExtractExistingFileAction ExtractExistingFile - { - get; - set; - } - - - /// - /// The action to take when an error is encountered while - /// opening or reading files as they are saved into a zip archive. - /// - /// - /// - /// - /// Errors can occur within a call to ZipFile.Save, as the various files contained - /// in a ZipFile are being saved into the zip archive. During the - /// Save, DotNetZip will perform a File.Open on the file - /// associated to the ZipEntry, and then will read the entire contents of - /// the file as it is zipped. Either the open or the Read may fail, because - /// of lock conflicts or other reasons. Using this property, you can - /// specify the action to take when such errors occur. - /// - /// - /// - /// Typically you will NOT set this property on individual ZipEntry - /// instances. Instead, you will set the ZipFile.ZipErrorAction property on - /// the ZipFile instance, before adding any entries to the - /// ZipFile. If you do this, errors encountered on behalf of any of - /// the entries in the ZipFile will be handled the same way. - /// - /// - /// - /// But, if you use a handler, you will want - /// to set this property on the ZipEntry within the handler, to - /// communicate back to DotNetZip what you would like to do with the - /// particular error. - /// - /// - /// - /// - /// - public ZipErrorAction ZipErrorAction - { - get; - set; - } - - - /// - /// Indicates whether the entry was included in the most recent save. - /// - /// - /// An entry can be excluded or skipped from a save if there is an error - /// opening or reading the entry. - /// - /// - public bool IncludedInMostRecentSave - { - get - { - return !_skippedDuringSave; - } - } - - - /// - /// A callback that allows the application to specify the compression to use - /// for a given entry that is about to be added to the zip archive. - /// - /// - /// - /// - /// See - /// - /// - public SetCompressionCallback SetCompression - { - get; - set; - } - - - - /// - /// Set to indicate whether to use UTF-8 encoding for filenames and comments. - /// - /// - /// - /// - /// - /// If this flag is set, the comment and filename for the entry will be - /// encoded with UTF-8, as described in the Zip - /// specification, if necessary. "Necessary" means, the filename or - /// entry comment (if any) cannot be reflexively encoded and decoded using the - /// default code page, IBM437. - /// - /// - /// - /// Setting this flag to true is equivalent to setting to System.Text.Encoding.UTF8. - /// - /// - /// - /// This flag has no effect or relation to the text encoding used within the - /// file itself. - /// - /// - /// - [Obsolete("Beginning with v1.9.1.6 of DotNetZip, this property is obsolete. It will be removed in a future version of the library. Your applications should use AlternateEncoding and AlternateEncodingUsage instead.")] - public bool UseUnicodeAsNecessary - { - get - { - return (AlternateEncoding == System.Text.Encoding.GetEncoding("UTF-8")) && - (AlternateEncodingUsage == ZipOption.AsNecessary); - } - set - { - if (value) - { - AlternateEncoding = System.Text.Encoding.GetEncoding("UTF-8"); - AlternateEncodingUsage = ZipOption.AsNecessary; - - } - else - { - AlternateEncoding = Ionic.Zip.ZipFile.DefaultEncoding; - AlternateEncodingUsage = ZipOption.Never; - } - } - } - - /// - /// The text encoding to use for the FileName and Comment on this ZipEntry, - /// when the default encoding is insufficient. - /// - /// - /// - /// - /// - /// Don't use this property. See . - /// - /// - /// - [Obsolete("This property is obsolete since v1.9.1.6. Use AlternateEncoding and AlternateEncodingUsage instead.", true)] - public System.Text.Encoding ProvisionalAlternateEncoding - { - get; set; - } - - /// - /// Specifies the alternate text encoding used by this ZipEntry - /// - /// - /// - /// The default text encoding used in Zip files for encoding filenames and - /// comments is IBM437, which is something like a superset of ASCII. In - /// cases where this is insufficient, applications can specify an - /// alternate encoding. - /// - /// - /// When creating a zip file, the usage of the alternate encoding is - /// governed by the property. - /// Typically you would set both properties to tell DotNetZip to employ an - /// encoding that is not IBM437 in the zipfile you are creating. - /// - /// - /// Keep in mind that because the ZIP specification states that the only - /// valid encodings to use are IBM437 and UTF-8, if you use something - /// other than that, then zip tools and libraries may not be able to - /// successfully read the zip archive you generate. - /// - /// - /// The zip specification states that applications should presume that - /// IBM437 is in use, except when a special bit is set, which indicates - /// UTF-8. There is no way to specify an arbitrary code page, within the - /// zip file itself. When you create a zip file encoded with gb2312 or - /// ibm861 or anything other than IBM437 or UTF-8, then the application - /// that reads the zip file needs to "know" which code page to use. In - /// some cases, the code page used when reading is chosen implicitly. For - /// example, WinRar uses the ambient code page for the host desktop - /// operating system. The pitfall here is that if you create a zip in - /// Copenhagen and send it to Tokyo, the reader of the zipfile may not be - /// able to decode successfully. - /// - /// - /// - /// This example shows how to create a zipfile encoded with a - /// language-specific encoding: - /// - /// using (var zip = new ZipFile()) - /// { - /// zip.AlternateEnoding = System.Text.Encoding.GetEncoding("ibm861"); - /// zip.AlternateEnodingUsage = ZipOption.Always; - /// zip.AddFileS(arrayOfFiles); - /// zip.Save("Myarchive-Encoded-in-IBM861.zip"); - /// } - /// - /// - /// - public System.Text.Encoding AlternateEncoding - { - get; set; - } - - - /// - /// Describes if and when this instance should apply - /// AlternateEncoding to encode the FileName and Comment, when - /// saving. - /// - /// - public ZipOption AlternateEncodingUsage - { - get; set; - } - - - // /// - // /// The text encoding actually used for this ZipEntry. - // /// - // /// - // /// - // /// - // /// - // /// This read-only property describes the encoding used by the - // /// ZipEntry. If the entry has been read in from an existing ZipFile, - // /// then it may take the value UTF-8, if the entry is coded to specify UTF-8. - // /// If the entry does not specify UTF-8, the typical case, then the encoding - // /// used is whatever the application specified in the call to - // /// ZipFile.Read(). If the application has used one of the overloads of - // /// ZipFile.Read() that does not accept an encoding parameter, then the - // /// encoding used is IBM437, which is the default encoding described in the - // /// ZIP specification. - // /// - // /// - // /// If the entry is being created, then the value of ActualEncoding is taken - // /// according to the logic described in the documentation for . - // /// - // /// - // /// An application might be interested in retrieving this property to see if - // /// an entry read in from a file has used Unicode (UTF-8). - // /// - // /// - // /// - // /// - // public System.Text.Encoding ActualEncoding - // { - // get - // { - // return _actualEncoding; - // } - // } - - - - - internal static string NameInArchive(String filename, string directoryPathInArchive) - { - string result = null; - if (directoryPathInArchive == null) - result = filename; - - else - { - if (String.IsNullOrEmpty(directoryPathInArchive)) - { - result = Path.GetFileName(filename); - } - else - { - // explicitly specify a pathname for this file - result = Path.Combine(directoryPathInArchive, Path.GetFileName(filename)); - } - } - - //result = Path.GetFullPath(result); - result = SharedUtilities.NormalizePathForUseInZipFile(result); - - return result; - } - - // workitem 9073 - internal static ZipEntry CreateFromNothing(String nameInArchive) - { - return Create(nameInArchive, ZipEntrySource.None, null, null); - } - - internal static ZipEntry CreateFromFile(String filename, string nameInArchive) - { - return Create(nameInArchive, ZipEntrySource.FileSystem, filename, null); - } - - internal static ZipEntry CreateForStream(String entryName, Stream s) - { - return Create(entryName, ZipEntrySource.Stream, s, null); - } - - internal static ZipEntry CreateForWriter(String entryName, WriteDelegate d) - { - return Create(entryName, ZipEntrySource.WriteDelegate, d, null); - } - - internal static ZipEntry CreateForJitStreamProvider(string nameInArchive, OpenDelegate opener, CloseDelegate closer) - { - return Create(nameInArchive, ZipEntrySource.JitStream, opener, closer); - } - - internal static ZipEntry CreateForZipOutputStream(string nameInArchive) - { - return Create(nameInArchive, ZipEntrySource.ZipOutputStream, null, null); - } - - - private static ZipEntry Create(string nameInArchive, ZipEntrySource source, Object arg1, Object arg2) - { - if (String.IsNullOrEmpty(nameInArchive)) - throw new Ionic.Zip.ZipException("The entry name must be non-null and non-empty."); - - ZipEntry entry = new ZipEntry(); - - // workitem 7071 - // workitem 7926 - "version made by" OS should be zero for compat with WinZip - entry._VersionMadeBy = (0 << 8) + 45; // indicates the attributes are FAT Attributes, and v4.5 of the spec - entry._Source = source; - entry._Mtime = entry._Atime = entry._Ctime = DateTime.UtcNow; - - if (source == ZipEntrySource.Stream) - { - entry._sourceStream = (arg1 as Stream); // may or may not be null - } - else if (source == ZipEntrySource.WriteDelegate) - { - entry._WriteDelegate = (arg1 as WriteDelegate); // may or may not be null - } - else if (source == ZipEntrySource.JitStream) - { - entry._OpenDelegate = (arg1 as OpenDelegate); // may or may not be null - entry._CloseDelegate = (arg2 as CloseDelegate); // may or may not be null - } - else if (source == ZipEntrySource.ZipOutputStream) - { - } - // workitem 9073 - else if (source == ZipEntrySource.None) - { - // make this a valid value, for later. - entry._Source = ZipEntrySource.FileSystem; - } - else - { - String filename = (arg1 as String); // must not be null - - if (String.IsNullOrEmpty(filename)) - throw new Ionic.Zip.ZipException("The filename must be non-null and non-empty."); - - try - { - // The named file may or may not exist at this time. For - // example, when adding a directory by name. We test existence - // when necessary: when saving the ZipFile, or when getting the - // attributes, and so on. - -#if NETCF - // workitem 6878 - // Ionic.Zip.SharedUtilities.AdjustTime_Win32ToDotNet - entry._Mtime = File.GetLastWriteTime(filename).ToUniversalTime(); - entry._Ctime = File.GetCreationTime(filename).ToUniversalTime(); - entry._Atime = File.GetLastAccessTime(filename).ToUniversalTime(); - - // workitem 7071 - // can only get attributes of files that exist. - if (File.Exists(filename) || Directory.Exists(filename)) - entry._ExternalFileAttrs = (int)NetCfFile.GetAttributes(filename); - -#elif SILVERLIGHT - entry._Mtime = - entry._Ctime = - entry._Atime = System.DateTime.UtcNow; - entry._ExternalFileAttrs = (int)0; -#else - // workitem 6878?? - entry._Mtime = File.GetLastWriteTime(filename).ToUniversalTime(); - entry._Ctime = File.GetCreationTime(filename).ToUniversalTime(); - entry._Atime = File.GetLastAccessTime(filename).ToUniversalTime(); - - // workitem 7071 - // can only get attributes on files that exist. - if (File.Exists(filename) || Directory.Exists(filename)) - entry._ExternalFileAttrs = (int)File.GetAttributes(filename); - -#endif - entry._ntfsTimesAreSet = true; - - entry._LocalFileName = Path.GetFullPath(filename); // workitem 8813 - - } - catch (System.IO.PathTooLongException ptle) - { - // workitem 14035 - var msg = String.Format("The path is too long, filename={0}", - filename); - throw new ZipException(msg, ptle); - } - - } - - entry._LastModified = entry._Mtime; - entry._FileNameInArchive = SharedUtilities.NormalizePathForUseInZipFile(nameInArchive); - // We don't actually slurp in the file data until the caller invokes Write on this entry. - - return entry; - } - - - - - internal void MarkAsDirectory() - { - _IsDirectory = true; - // workitem 6279 - if (!_FileNameInArchive.EndsWith("/")) - _FileNameInArchive += "/"; - } - - - - /// - /// Indicates whether an entry is marked as a text file. Be careful when - /// using on this property. Unless you have a good reason, you should - /// probably ignore this property. - /// - /// - /// - /// - /// The ZIP format includes a provision for specifying whether an entry in - /// the zip archive is a text or binary file. This property exposes that - /// metadata item. Be careful when using this property: It's not clear - /// that this property as a firm meaning, across tools and libraries. - /// - /// - /// - /// To be clear, when reading a zip file, the property value may or may - /// not be set, and its value may or may not be valid. Not all entries - /// that you may think of as "text" entries will be so marked, and entries - /// marked as "text" are not guaranteed in any way to be text entries. - /// Whether the value is set and set correctly depends entirely on the - /// application that produced the zip file. - /// - /// - /// - /// There are many zip tools available, and when creating zip files, some - /// of them "respect" the IsText metadata field, and some of them do not. - /// Unfortunately, even when an application tries to do "the right thing", - /// it's not always clear what "the right thing" is. - /// - /// - /// - /// There's no firm definition of just what it means to be "a text file", - /// and the zip specification does not help in this regard. Twenty years - /// ago, text was ASCII, each byte was less than 127. IsText meant, all - /// bytes in the file were less than 127. These days, it is not the case - /// that all text files have all bytes less than 127. Any unicode file - /// may have bytes that are above 0x7f. The zip specification has nothing - /// to say on this topic. Therefore, it's not clear what IsText really - /// means. - /// - /// - /// - /// This property merely tells a reading application what is stored in the - /// metadata for an entry, without guaranteeing its validity or its - /// meaning. - /// - /// - /// - /// When DotNetZip is used to create a zipfile, it attempts to set this - /// field "correctly." For example, if a file ends in ".txt", this field - /// will be set. Your application may override that default setting. When - /// writing a zip file, you must set the property before calling - /// Save() on the ZipFile. - /// - /// - /// - /// When reading a zip file, a more general way to decide just what kind - /// of file is contained in a particular entry is to use the file type - /// database stored in the operating system. The operating system stores - /// a table that says, a file with .jpg extension is a JPG image file, a - /// file with a .xml extension is an XML document, a file with a .txt is a - /// pure ASCII text document, and so on. To get this information on - /// Windows, you - /// need to read and parse the registry. - /// - /// - /// - /// - /// using (var zip = new ZipFile()) - /// { - /// var e = zip.UpdateFile("Descriptions.mme", ""); - /// e.IsText = true; - /// zip.Save(zipPath); - /// } - /// - /// - /// - /// Using zip As New ZipFile - /// Dim e2 as ZipEntry = zip.AddFile("Descriptions.mme", "") - /// e.IsText= True - /// zip.Save(zipPath) - /// End Using - /// - /// - public bool IsText - { - // workitem 7801 - get { return _IsText; } - set { _IsText = value; } - } - - - - /// Provides a string representation of the instance. - /// a string representation of the instance. - public override String ToString() - { - return String.Format("ZipEntry::{0}", FileName); - } - - - internal Stream ArchiveStream - { - get - { - if (_archiveStream == null) - { - if (_container.ZipFile != null) - { - var zf = _container.ZipFile; - zf.Reset(false); - _archiveStream = zf.StreamForDiskNumber(_diskNumber); - } - else - { - _archiveStream = _container.ZipOutputStream.OutputStream; - } - } - return _archiveStream; - } - } - - - private void SetFdpLoh() - { - // The value for FileDataPosition has not yet been set. - // Therefore, seek to the local header, and figure the start of file data. - // workitem 8098: ok (restore) - long origPosition = this.ArchiveStream.Position; - try - { - this.ArchiveStream.Seek(this._RelativeOffsetOfLocalHeader, SeekOrigin.Begin); - - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream); - } - catch (System.IO.IOException exc1) - { - string description = String.Format("Exception seeking entry({0}) offset(0x{1:X8}) len(0x{2:X8})", - this.FileName, this._RelativeOffsetOfLocalHeader, - this.ArchiveStream.Length); - throw new BadStateException(description, exc1); - } - - byte[] block = new byte[30]; - this.ArchiveStream.Read(block, 0, block.Length); - - // At this point we could verify the contents read from the local header - // with the contents read from the central header. We could, but don't need to. - // So we won't. - - Int16 filenameLength = (short)(block[26] + block[27] * 256); - Int16 extraFieldLength = (short)(block[28] + block[29] * 256); - - // Console.WriteLine(" pos 0x{0:X8} ({0})", this.ArchiveStream.Position); - // Console.WriteLine(" seek 0x{0:X8} ({0})", filenameLength + extraFieldLength); - - this.ArchiveStream.Seek(filenameLength + extraFieldLength, SeekOrigin.Current); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream); - - this._LengthOfHeader = 30 + extraFieldLength + filenameLength + - GetLengthOfCryptoHeaderBytes(_Encryption_FromZipFile); - - // Console.WriteLine(" ROLH 0x{0:X8} ({0})", _RelativeOffsetOfLocalHeader); - // Console.WriteLine(" LOH 0x{0:X8} ({0})", _LengthOfHeader); - // workitem 8098: ok (arithmetic) - this.__FileDataPosition = _RelativeOffsetOfLocalHeader + _LengthOfHeader; - // Console.WriteLine(" FDP 0x{0:X8} ({0})", __FileDataPosition); - - // restore file position: - // workitem 8098: ok (restore) - this.ArchiveStream.Seek(origPosition, SeekOrigin.Begin); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(this.ArchiveStream); - } - - - -#if AESCRYPTO - private static int GetKeyStrengthInBits(EncryptionAlgorithm a) - { - if (a == EncryptionAlgorithm.WinZipAes256) return 256; - else if (a == EncryptionAlgorithm.WinZipAes128) return 128; - return -1; - } -#endif - - internal static int GetLengthOfCryptoHeaderBytes(EncryptionAlgorithm a) - { - //if ((_BitField & 0x01) != 0x01) return 0; - if (a == EncryptionAlgorithm.None) return 0; - -#if AESCRYPTO - if (a == EncryptionAlgorithm.WinZipAes128 || - a == EncryptionAlgorithm.WinZipAes256) - { - int KeyStrengthInBits = GetKeyStrengthInBits(a); - int sizeOfSaltAndPv = ((KeyStrengthInBits / 8 / 2) + 2); - return sizeOfSaltAndPv; - } -#endif - if (a == EncryptionAlgorithm.PkzipWeak) - return 12; - throw new ZipException("internal error"); - } - - - internal long FileDataPosition - { - get - { - if (__FileDataPosition == -1) - SetFdpLoh(); - - return __FileDataPosition; - } - } - - private int LengthOfHeader - { - get - { - if (_LengthOfHeader == 0) - SetFdpLoh(); - - return _LengthOfHeader; - } - } - - - - private ZipCrypto _zipCrypto_forExtract; - private ZipCrypto _zipCrypto_forWrite; -#if AESCRYPTO - private WinZipAesCrypto _aesCrypto_forExtract; - private WinZipAesCrypto _aesCrypto_forWrite; - private Int16 _WinZipAesMethod; -#endif - - internal DateTime _LastModified; - private DateTime _Mtime, _Atime, _Ctime; // workitem 6878: NTFS quantities - private bool _ntfsTimesAreSet; - private bool _emitNtfsTimes = true; - private bool _emitUnixTimes; // by default, false - private bool _TrimVolumeFromFullyQualifiedPaths = true; // by default, trim them. - internal string _LocalFileName; - private string _FileNameInArchive; - internal Int16 _VersionNeeded; - internal Int16 _BitField; - internal Int16 _CompressionMethod; - private Int16 _CompressionMethod_FromZipFile; - private Ionic.Zlib.CompressionLevel _CompressionLevel; - internal string _Comment; - private bool _IsDirectory; - private byte[] _CommentBytes; - internal Int64 _CompressedSize; - internal Int64 _CompressedFileDataSize; // CompressedSize less 12 bytes for the encryption header, if any - internal Int64 _UncompressedSize; - internal Int32 _TimeBlob; - private bool _crcCalculated; - internal Int32 _Crc32; - internal byte[] _Extra; - private bool _metadataChanged; - private bool _restreamRequiredOnSave; - private bool _sourceIsEncrypted; - private bool _skippedDuringSave; - private UInt32 _diskNumber; - - private static System.Text.Encoding ibm437 = System.Text.Encoding.GetEncoding("IBM437"); - //private System.Text.Encoding _provisionalAlternateEncoding = System.Text.Encoding.GetEncoding("IBM437"); - private System.Text.Encoding _actualEncoding; - - internal ZipContainer _container; - - private long __FileDataPosition = -1; - private byte[] _EntryHeader; - internal Int64 _RelativeOffsetOfLocalHeader; - private Int64 _future_ROLH; - private Int64 _TotalEntrySize; - private int _LengthOfHeader; - private int _LengthOfTrailer; - internal bool _InputUsesZip64; - private UInt32 _UnsupportedAlgorithmId; - - internal string _Password; - internal ZipEntrySource _Source; - internal EncryptionAlgorithm _Encryption; - internal EncryptionAlgorithm _Encryption_FromZipFile; - internal byte[] _WeakEncryptionHeader; - internal Stream _archiveStream; - private Stream _sourceStream; - private Nullable _sourceStreamOriginalPosition; - private bool _sourceWasJitProvided; - private bool _ioOperationCanceled; - private bool _presumeZip64; - private Nullable _entryRequiresZip64; - private Nullable _OutputUsesZip64; - private bool _IsText; // workitem 7801 - private ZipEntryTimestamp _timestamp; - - private static System.DateTime _unixEpoch = new System.DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); - private static System.DateTime _win32Epoch = System.DateTime.FromFileTimeUtc(0L); - private static System.DateTime _zeroHour = new System.DateTime(1, 1, 1, 0, 0, 0, DateTimeKind.Utc); - - private WriteDelegate _WriteDelegate; - private OpenDelegate _OpenDelegate; - private CloseDelegate _CloseDelegate; - - - // summary - // The default size of the IO buffer for ZipEntry instances. Currently it is 8192 bytes. - // summary - //public const int IO_BUFFER_SIZE_DEFAULT = 8192; // 0x8000; // 0x4400 - - } - - - - /// - /// An enum that specifies the type of timestamp available on the ZipEntry. - /// - /// - /// - /// - /// - /// The last modified time of a file can be stored in multiple ways in - /// a zip file, and they are not mutually exclusive: - /// - /// - /// - /// - /// In the so-called "DOS" format, which has a 2-second precision. Values - /// are rounded to the nearest even second. For example, if the time on the - /// file is 12:34:43, then it will be stored as 12:34:44. This first value - /// is accessible via the LastModified property. This value is always - /// present in the metadata for each zip entry. In some cases the value is - /// invalid, or zero. - /// - /// - /// - /// In the so-called "Windows" or "NTFS" format, as an 8-byte integer - /// quantity expressed as the number of 1/10 milliseconds (in other words - /// the number of 100 nanosecond units) since January 1, 1601 (UTC). This - /// format is how Windows represents file times. This time is accessible - /// via the ModifiedTime property. - /// - /// - /// - /// In the "Unix" format, a 4-byte quantity specifying the number of seconds since - /// January 1, 1970 UTC. - /// - /// - /// - /// In an older format, now deprecated but still used by some current - /// tools. This format is also a 4-byte quantity specifying the number of - /// seconds since January 1, 1970 UTC. - /// - /// - /// - /// - /// - /// This bit field describes which of the formats were found in a ZipEntry that was read. - /// - /// - /// - [Flags] - public enum ZipEntryTimestamp - { - /// - /// Default value. - /// - None = 0, - - /// - /// A DOS timestamp with 2-second precision. - /// - DOS = 1, - - /// - /// A Windows timestamp with 100-ns precision. - /// - Windows = 2, - - /// - /// A Unix timestamp with 1-second precision. - /// - Unix = 4, - - /// - /// A Unix timestamp with 1-second precision, stored in InfoZip v1 format. This - /// format is outdated and is supported for reading archives only. - /// - InfoZip1 = 8, - } - - - - /// - /// The method of compression to use for a particular ZipEntry. - /// - /// - /// - /// PKWare's - /// ZIP Specification describes a number of distinct - /// cmopression methods that can be used within a zip - /// file. DotNetZip supports a subset of them. - /// - public enum CompressionMethod - { - /// - /// No compression at all. For COM environments, the value is 0 (zero). - /// - None = 0, - - /// - /// DEFLATE compression, as described in IETF RFC - /// 1951. This is the "normal" compression used in zip - /// files. For COM environments, the value is 8. - /// - Deflate = 8, - -#if BZIP - /// - /// BZip2 compression, a compression algorithm developed by Julian Seward. - /// For COM environments, the value is 12. - /// - BZip2 = 12, -#endif - } - - -#if NETCF - internal class NetCfFile - { - public static int SetTimes(string filename, DateTime ctime, DateTime atime, DateTime mtime) - { - IntPtr hFile = (IntPtr) CreateFileCE(filename, - (uint)0x40000000L, // (uint)FileAccess.Write, - (uint)0x00000002L, // (uint)FileShare.Write, - 0, - (uint) 3, // == open existing - (uint)0, // flagsAndAttributes - 0); - - if((int)hFile == -1) - { - // workitem 7944: don't throw on failure to set file times - // throw new ZipException("CreateFileCE Failed"); - return Interop.Marshal.GetLastWin32Error(); - } - - SetFileTime(hFile, - BitConverter.GetBytes(ctime.ToFileTime()), - BitConverter.GetBytes(atime.ToFileTime()), - BitConverter.GetBytes(mtime.ToFileTime())); - - CloseHandle(hFile); - return 0; - } - - - public static int SetLastWriteTime(string filename, DateTime mtime) - { - IntPtr hFile = (IntPtr) CreateFileCE(filename, - (uint)0x40000000L, // (uint)FileAccess.Write, - (uint)0x00000002L, // (uint)FileShare.Write, - 0, - (uint) 3, // == open existing - (uint)0, // flagsAndAttributes - 0); - - if((int)hFile == -1) - { - // workitem 7944: don't throw on failure to set file time - // throw new ZipException(String.Format("CreateFileCE Failed ({0})", - // Interop.Marshal.GetLastWin32Error())); - return Interop.Marshal.GetLastWin32Error(); - } - - SetFileTime(hFile, null, null, - BitConverter.GetBytes(mtime.ToFileTime())); - - CloseHandle(hFile); - return 0; - } - - - [Interop.DllImport("coredll.dll", EntryPoint="CreateFile", SetLastError=true)] - internal static extern int CreateFileCE(string lpFileName, - uint dwDesiredAccess, - uint dwShareMode, - int lpSecurityAttributes, - uint dwCreationDisposition, - uint dwFlagsAndAttributes, - int hTemplateFile); - - - [Interop.DllImport("coredll", EntryPoint="GetFileAttributes", SetLastError=true)] - internal static extern uint GetAttributes(string lpFileName); - - [Interop.DllImport("coredll", EntryPoint="SetFileAttributes", SetLastError=true)] - internal static extern bool SetAttributes(string lpFileName, uint dwFileAttributes); - - [Interop.DllImport("coredll", EntryPoint="SetFileTime", SetLastError=true)] - internal static extern bool SetFileTime(IntPtr hFile, byte[] lpCreationTime, byte[] lpLastAccessTime, byte[] lpLastWriteTime); - - [Interop.DllImport("coredll.dll", SetLastError=true)] - internal static extern bool CloseHandle(IntPtr hObject); - - } -#endif - - - -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntrySource.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntrySource.cs deleted file mode 100644 index b64380df..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipEntrySource.cs +++ /dev/null @@ -1,69 +0,0 @@ -// ZipEntrySource.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2009 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: <2009-November-19 11:18:42> -// -// ------------------------------------------------------------------ -// - -namespace Ionic.Zip -{ - /// - /// An enum that specifies the source of the ZipEntry. - /// - public enum ZipEntrySource - { - /// - /// Default value. Invalid on a bonafide ZipEntry. - /// - None = 0, - - /// - /// The entry was instantiated by calling AddFile() or another method that - /// added an entry from the filesystem. - /// - FileSystem, - - /// - /// The entry was instantiated via or - /// . - /// - Stream, - - /// - /// The ZipEntry was instantiated by reading a zipfile. - /// - ZipFile, - - /// - /// The content for the ZipEntry will be or was provided by the WriteDelegate. - /// - WriteDelegate, - - /// - /// The content for the ZipEntry will be obtained from the stream dispensed by the OpenDelegate. - /// The entry was instantiated via . - /// - JitStream, - - /// - /// The content for the ZipEntry will be or was obtained from a ZipOutputStream. - /// - ZipOutputStream, - } - -} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipErrorAction.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipErrorAction.cs deleted file mode 100644 index 3a394cd2..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipErrorAction.cs +++ /dev/null @@ -1,97 +0,0 @@ -// ZipErrorAction.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2009 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: <2009-September-01 18:43:20> -// -// ------------------------------------------------------------------ -// -// This module defines the ZipErrorAction enum, which provides -// an action to take when errors occur when opening or reading -// files to be added to a zip file. -// -// ------------------------------------------------------------------ - - -namespace Ionic.Zip -{ - /// - /// An enum providing the options when an error occurs during opening or reading - /// of a file or directory that is being saved to a zip file. - /// - /// - /// - /// - /// This enum describes the actions that the library can take when an error occurs - /// opening or reading a file, as it is being saved into a Zip archive. - /// - /// - /// - /// In some cases an error will occur when DotNetZip tries to open a file to be - /// added to the zip archive. In other cases, an error might occur after the - /// file has been successfully opened, while DotNetZip is reading the file. - /// - /// - /// - /// The first problem might occur when calling AddDirectory() on a directory - /// that contains a Clipper .dbf file; the file is locked by Clipper and - /// cannot be opened by another process. An example of the second problem is - /// the ERROR_LOCK_VIOLATION that results when a file is opened by another - /// process, but not locked, and a range lock has been taken on the file. - /// Microsoft Outlook takes range locks on .PST files. - /// - /// - public enum ZipErrorAction - { - /// - /// Throw an exception when an error occurs while zipping. This is the default - /// behavior. (For COM clients, this is a 0 (zero).) - /// - Throw, - - /// - /// When an error occurs during zipping, for example a file cannot be opened, - /// skip the file causing the error, and continue zipping. (For COM clients, - /// this is a 1.) - /// - Skip, - - /// - /// When an error occurs during zipping, for example a file cannot be opened, - /// retry the operation that caused the error. Be careful with this option. If - /// the error is not temporary, the library will retry forever. (For COM - /// clients, this is a 2.) - /// - Retry, - - /// - /// When an error occurs, invoke the zipError event. The event type used is - /// . A typical use of this option: - /// a GUI application may wish to pop up a dialog to allow the user to view the - /// error that occurred, and choose an appropriate action. After your - /// processing in the error event, if you want to skip the file, set on the - /// ZipProgressEventArgs.CurrentEntry to Skip. If you want the - /// exception to be thrown, set ZipErrorAction on the CurrentEntry - /// to Throw. If you want to cancel the zip, set - /// ZipProgressEventArgs.Cancel to true. Cancelling differs from using - /// Skip in that a cancel will not save any further entries, if there are any. - /// (For COM clients, the value of this enum is a 3.) - /// - InvokeErrorEvent, - } - -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.AddUpdate.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.AddUpdate.cs deleted file mode 100644 index d5da4fc4..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.AddUpdate.cs +++ /dev/null @@ -1,2182 +0,0 @@ -// ZipFile.AddUpdate.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-November-01 13:56:58> -// -// ------------------------------------------------------------------ -// -// This module defines the methods for Adding and Updating entries in -// the ZipFile. -// -// ------------------------------------------------------------------ -// - - -using System; -using System.IO; -using System.Collections.Generic; - -namespace Ionic.Zip -{ - public partial class ZipFile - { - /// - /// Adds an item, either a file or a directory, to a zip file archive. - /// - /// - /// - /// - /// This method is handy if you are adding things to zip archive and don't - /// want to bother distinguishing between directories or files. Any files are - /// added as single entries. A directory added through this method is added - /// recursively: all files and subdirectories contained within the directory - /// are added to the ZipFile. - /// - /// - /// - /// The name of the item may be a relative path or a fully-qualified - /// path. Remember, the items contained in ZipFile instance get written - /// to the disk only when you call or a similar - /// save method. - /// - /// - /// - /// The directory name used for the file within the archive is the same - /// as the directory name (potentially a relative path) specified in the - /// . - /// - /// - /// - /// For ZipFile properties including , , , , , - /// , and , their - /// respective values at the time of this call will be applied to the - /// ZipEntry added. - /// - /// - /// - /// - /// - /// - /// - /// - /// This method has two overloads. - /// - /// the name of the file or directory to add. - /// - /// The ZipEntry added. - public ZipEntry AddItem(string fileOrDirectoryName) - { - return AddItem(fileOrDirectoryName, null); - } - - - /// - /// Adds an item, either a file or a directory, to a zip file archive, - /// explicitly specifying the directory path to be used in the archive. - /// - /// - /// - /// - /// If adding a directory, the add is recursive on all files and - /// subdirectories contained within it. - /// - /// - /// The name of the item may be a relative path or a fully-qualified path. - /// The item added by this call to the ZipFile is not read from the - /// disk nor written to the zip file archive until the application calls - /// Save() on the ZipFile. - /// - /// - /// - /// This version of the method allows the caller to explicitly specify the - /// directory path to be used in the archive, which would override the - /// "natural" path of the filesystem file. - /// - /// - /// - /// Encryption will be used on the file data if the Password has - /// been set on the ZipFile object, prior to calling this method. - /// - /// - /// - /// For ZipFile properties including , , , , , - /// , and , their - /// respective values at the time of this call will be applied to the - /// ZipEntry added. - /// - /// - /// - /// - /// - /// Thrown if the file or directory passed in does not exist. - /// - /// - /// the name of the file or directory to add. - /// - /// - /// - /// The name of the directory path to use within the zip archive. This path - /// need not refer to an extant directory in the current filesystem. If the - /// files within the zip are later extracted, this is the path used for the - /// extracted file. Passing null (Nothing in VB) will use the - /// path on the fileOrDirectoryName. Passing the empty string ("") will - /// insert the item at the root path within the archive. - /// - /// - /// - /// - /// - /// - /// - /// This example shows how to zip up a set of files into a flat hierarchy, - /// regardless of where in the filesystem the files originated. The resulting - /// zip archive will contain a toplevel directory named "flat", which itself - /// will contain files Readme.txt, MyProposal.docx, and Image1.jpg. A - /// subdirectory under "flat" called SupportFiles will contain all the files - /// in the "c:\SupportFiles" directory on disk. - /// - /// - /// String[] itemnames= { - /// "c:\\fixedContent\\Readme.txt", - /// "MyProposal.docx", - /// "c:\\SupportFiles", // a directory - /// "images\\Image1.jpg" - /// }; - /// - /// try - /// { - /// using (ZipFile zip = new ZipFile()) - /// { - /// for (int i = 1; i < itemnames.Length; i++) - /// { - /// // will add Files or Dirs, recurses and flattens subdirectories - /// zip.AddItem(itemnames[i],"flat"); - /// } - /// zip.Save(ZipToCreate); - /// } - /// } - /// catch (System.Exception ex1) - /// { - /// System.Console.Error.WriteLine("exception: {0}", ex1); - /// } - /// - /// - /// - /// Dim itemnames As String() = _ - /// New String() { "c:\fixedContent\Readme.txt", _ - /// "MyProposal.docx", _ - /// "SupportFiles", _ - /// "images\Image1.jpg" } - /// Try - /// Using zip As New ZipFile - /// Dim i As Integer - /// For i = 1 To itemnames.Length - 1 - /// ' will add Files or Dirs, recursing and flattening subdirectories. - /// zip.AddItem(itemnames(i), "flat") - /// Next i - /// zip.Save(ZipToCreate) - /// End Using - /// Catch ex1 As Exception - /// Console.Error.WriteLine("exception: {0}", ex1.ToString()) - /// End Try - /// - /// - /// The ZipEntry added. - public ZipEntry AddItem(String fileOrDirectoryName, String directoryPathInArchive) - { - if (File.Exists(fileOrDirectoryName)) - return AddFile(fileOrDirectoryName, directoryPathInArchive); - - if (Directory.Exists(fileOrDirectoryName)) - return AddDirectory(fileOrDirectoryName, directoryPathInArchive); - - throw new FileNotFoundException(String.Format("That file or directory ({0}) does not exist!", - fileOrDirectoryName)); - } - - /// - /// Adds a File to a Zip file archive. - /// - /// - /// - /// - /// This call collects metadata for the named file in the filesystem, - /// including the file attributes and the timestamp, and inserts that metadata - /// into the resulting ZipEntry. Only when the application calls Save() on - /// the ZipFile, does DotNetZip read the file from the filesystem and - /// then write the content to the zip file archive. - /// - /// - /// - /// This method will throw an exception if an entry with the same name already - /// exists in the ZipFile. - /// - /// - /// - /// For ZipFile properties including , , , , , - /// , and , their - /// respective values at the time of this call will be applied to the - /// ZipEntry added. - /// - /// - /// - /// - /// - /// - /// In this example, three files are added to a Zip archive. The ReadMe.txt - /// file will be placed in the root of the archive. The .png file will be - /// placed in a folder within the zip called photos\personal. The pdf file - /// will be included into a folder within the zip called Desktop. - /// - /// - /// try - /// { - /// using (ZipFile zip = new ZipFile()) - /// { - /// zip.AddFile("c:\\photos\\personal\\7440-N49th.png"); - /// zip.AddFile("c:\\Desktop\\2008-Regional-Sales-Report.pdf"); - /// zip.AddFile("ReadMe.txt"); - /// - /// zip.Save("Package.zip"); - /// } - /// } - /// catch (System.Exception ex1) - /// { - /// System.Console.Error.WriteLine("exception: " + ex1); - /// } - /// - /// - /// - /// Try - /// Using zip As ZipFile = New ZipFile - /// zip.AddFile("c:\photos\personal\7440-N49th.png") - /// zip.AddFile("c:\Desktop\2008-Regional-Sales-Report.pdf") - /// zip.AddFile("ReadMe.txt") - /// zip.Save("Package.zip") - /// End Using - /// Catch ex1 As Exception - /// Console.Error.WriteLine("exception: {0}", ex1.ToString) - /// End Try - /// - /// - /// - /// This method has two overloads. - /// - /// - /// - /// - /// - /// - /// The name of the file to add. It should refer to a file in the filesystem. - /// The name of the file may be a relative path or a fully-qualified path. - /// - /// The ZipEntry corresponding to the File added. - public ZipEntry AddFile(string fileName) - { - return AddFile(fileName, null); - } - - - - - - /// - /// Adds a File to a Zip file archive, potentially overriding the path to be - /// used within the zip archive. - /// - /// - /// - /// - /// The file added by this call to the ZipFile is not written to the - /// zip file archive until the application calls Save() on the ZipFile. - /// - /// - /// - /// This method will throw an exception if an entry with the same name already - /// exists in the ZipFile. - /// - /// - /// - /// This version of the method allows the caller to explicitly specify the - /// directory path to be used in the archive. - /// - /// - /// - /// For ZipFile properties including , , , , , - /// , and , their - /// respective values at the time of this call will be applied to the - /// ZipEntry added. - /// - /// - /// - /// - /// - /// - /// In this example, three files are added to a Zip archive. The ReadMe.txt - /// file will be placed in the root of the archive. The .png file will be - /// placed in a folder within the zip called images. The pdf file will be - /// included into a folder within the zip called files\docs, and will be - /// encrypted with the given password. - /// - /// - /// try - /// { - /// using (ZipFile zip = new ZipFile()) - /// { - /// // the following entry will be inserted at the root in the archive. - /// zip.AddFile("c:\\datafiles\\ReadMe.txt", ""); - /// // this image file will be inserted into the "images" directory in the archive. - /// zip.AddFile("c:\\photos\\personal\\7440-N49th.png", "images"); - /// // the following will result in a password-protected file called - /// // files\\docs\\2008-Regional-Sales-Report.pdf in the archive. - /// zip.Password = "EncryptMe!"; - /// zip.AddFile("c:\\Desktop\\2008-Regional-Sales-Report.pdf", "files\\docs"); - /// zip.Save("Archive.zip"); - /// } - /// } - /// catch (System.Exception ex1) - /// { - /// System.Console.Error.WriteLine("exception: {0}", ex1); - /// } - /// - /// - /// - /// Try - /// Using zip As ZipFile = New ZipFile - /// ' the following entry will be inserted at the root in the archive. - /// zip.AddFile("c:\datafiles\ReadMe.txt", "") - /// ' this image file will be inserted into the "images" directory in the archive. - /// zip.AddFile("c:\photos\personal\7440-N49th.png", "images") - /// ' the following will result in a password-protected file called - /// ' files\\docs\\2008-Regional-Sales-Report.pdf in the archive. - /// zip.Password = "EncryptMe!" - /// zip.AddFile("c:\Desktop\2008-Regional-Sales-Report.pdf", "files\documents") - /// zip.Save("Archive.zip") - /// End Using - /// Catch ex1 As Exception - /// Console.Error.WriteLine("exception: {0}", ex1) - /// End Try - /// - /// - /// - /// - /// - /// - /// - /// - /// The name of the file to add. The name of the file may be a relative path - /// or a fully-qualified path. - /// - /// - /// - /// Specifies a directory path to use to override any path in the fileName. - /// This path may, or may not, correspond to a real directory in the current - /// filesystem. If the files within the zip are later extracted, this is the - /// path used for the extracted file. Passing null (Nothing in - /// VB) will use the path on the fileName, if any. Passing the empty string - /// ("") will insert the item at the root path within the archive. - /// - /// - /// The ZipEntry corresponding to the file added. - public ZipEntry AddFile(string fileName, String directoryPathInArchive) - { - string nameInArchive = ZipEntry.NameInArchive(fileName, directoryPathInArchive); - ZipEntry ze = ZipEntry.CreateFromFile(fileName, nameInArchive); - if (Verbose) StatusMessageTextWriter.WriteLine("adding {0}...", fileName); - return _InternalAddEntry(ze); - } - - - /// - /// This method removes a collection of entries from the ZipFile. - /// - /// - /// - /// A collection of ZipEntry instances from this zip file to be removed. For - /// example, you can pass in an array of ZipEntry instances; or you can call - /// SelectEntries(), and then add or remove entries from that - /// ICollection<ZipEntry> (ICollection(Of ZipEntry) in VB), and pass - /// that ICollection to this method. - /// - /// - /// - /// - public void RemoveEntries(System.Collections.Generic.ICollection entriesToRemove) - { - if (entriesToRemove == null) - throw new ArgumentNullException("entriesToRemove"); - - foreach (ZipEntry e in entriesToRemove) - { - this.RemoveEntry(e); - } - } - - - /// - /// This method removes a collection of entries from the ZipFile, by name. - /// - /// - /// - /// A collection of strings that refer to names of entries to be removed - /// from the ZipFile. For example, you can pass in an array or a - /// List of Strings that provide the names of entries to be removed. - /// - /// - /// - /// - public void RemoveEntries(System.Collections.Generic.ICollection entriesToRemove) - { - if (entriesToRemove == null) - throw new ArgumentNullException("entriesToRemove"); - - foreach (String e in entriesToRemove) - { - this.RemoveEntry(e); - } - } - - - /// - /// This method adds a set of files to the ZipFile. - /// - /// - /// - /// - /// Use this method to add a set of files to the zip archive, in one call. - /// For example, a list of files received from - /// System.IO.Directory.GetFiles() can be added to a zip archive in one - /// call. - /// - /// - /// - /// For ZipFile properties including , , , , , - /// , and , their - /// respective values at the time of this call will be applied to each - /// ZipEntry added. - /// - /// - /// - /// - /// The collection of names of the files to add. Each string should refer to a - /// file in the filesystem. The name of the file may be a relative path or a - /// fully-qualified path. - /// - /// - /// - /// This example shows how to create a zip file, and add a few files into it. - /// - /// String ZipFileToCreate = "archive1.zip"; - /// String DirectoryToZip = "c:\\reports"; - /// using (ZipFile zip = new ZipFile()) - /// { - /// // Store all files found in the top level directory, into the zip archive. - /// String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip); - /// zip.AddFiles(filenames); - /// zip.Save(ZipFileToCreate); - /// } - /// - /// - /// - /// Dim ZipFileToCreate As String = "archive1.zip" - /// Dim DirectoryToZip As String = "c:\reports" - /// Using zip As ZipFile = New ZipFile - /// ' Store all files found in the top level directory, into the zip archive. - /// Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip) - /// zip.AddFiles(filenames) - /// zip.Save(ZipFileToCreate) - /// End Using - /// - /// - /// - /// - public void AddFiles(System.Collections.Generic.IEnumerable fileNames) - { - this.AddFiles(fileNames, null); - } - - - /// - /// Adds or updates a set of files in the ZipFile. - /// - /// - /// - /// - /// Any files that already exist in the archive are updated. Any files that - /// don't yet exist in the archive are added. - /// - /// - /// - /// For ZipFile properties including , , , , , - /// , and , their - /// respective values at the time of this call will be applied to each - /// ZipEntry added. - /// - /// - /// - /// - /// The collection of names of the files to update. Each string should refer to a file in - /// the filesystem. The name of the file may be a relative path or a fully-qualified path. - /// - /// - public void UpdateFiles(System.Collections.Generic.IEnumerable fileNames) - { - this.UpdateFiles(fileNames, null); - } - - - /// - /// Adds a set of files to the ZipFile, using the - /// specified directory path in the archive. - /// - /// - /// - /// - /// Any directory structure that may be present in the - /// filenames contained in the list is "flattened" in the - /// archive. Each file in the list is added to the archive in - /// the specified top-level directory. - /// - /// - /// - /// For ZipFile properties including , , , , , , and , their respective values at the - /// time of this call will be applied to each ZipEntry added. - /// - /// - /// - /// - /// The names of the files to add. Each string should refer to - /// a file in the filesystem. The name of the file may be a - /// relative path or a fully-qualified path. - /// - /// - /// - /// Specifies a directory path to use to override any path in the file name. - /// Th is path may, or may not, correspond to a real directory in the current - /// filesystem. If the files within the zip are later extracted, this is the - /// path used for the extracted file. Passing null (Nothing in - /// VB) will use the path on each of the fileNames, if any. Passing - /// the empty string ("") will insert the item at the root path within the - /// archive. - /// - /// - /// - public void AddFiles(System.Collections.Generic.IEnumerable fileNames, String directoryPathInArchive) - { - AddFiles(fileNames, false, directoryPathInArchive); - } - - - - /// - /// Adds a set of files to the ZipFile, using the specified directory - /// path in the archive, and preserving the full directory structure in the - /// filenames. - /// - /// - /// - /// - /// - /// Think of the as a "root" or - /// base directory used in the archive for the files that get added. when - /// is true, the hierarchy of files - /// found in the filesystem will be placed, with the hierarchy intact, - /// starting at that root in the archive. When preserveDirHierarchy - /// is false, the path hierarchy of files is flattned, and the flattened - /// set of files gets placed in the root within the archive as specified in - /// directoryPathInArchive. - /// - /// - /// - /// For ZipFile properties including , , , , , - /// , and , their - /// respective values at the time of this call will be applied to each - /// ZipEntry added. - /// - /// - /// - /// - /// - /// The names of the files to add. Each string should refer to a file in the - /// filesystem. The name of the file may be a relative path or a - /// fully-qualified path. - /// - /// - /// - /// Specifies a directory path to use as a prefix for each entry name. - /// This path may, or may not, correspond to a real directory in the current - /// filesystem. If the files within the zip are later extracted, this is the - /// path used for the extracted file. Passing null (Nothing in - /// VB) will use the path on each of the fileNames, if any. Passing - /// the empty string ("") will insert the item at the root path within the - /// archive. - /// - /// - /// - /// whether the entries in the zip archive will reflect the directory - /// hierarchy that is present in the various filenames. For example, if - /// includes two paths, - /// \Animalia\Chordata\Mammalia\Info.txt and - /// \Plantae\Magnoliophyta\Dicotyledon\Info.txt, then calling this method - /// with = false will - /// result in an exception because of a duplicate entry name, while - /// calling this method with = - /// true will result in the full direcory paths being included in - /// the entries added to the ZipFile. - /// - /// - public void AddFiles(System.Collections.Generic.IEnumerable fileNames, - bool preserveDirHierarchy, - String directoryPathInArchive) - { - if (fileNames == null) - throw new ArgumentNullException("fileNames"); - - _addOperationCanceled = false; - OnAddStarted(); - if (preserveDirHierarchy) - { - foreach (var f in fileNames) - { - if (_addOperationCanceled) break; - if (directoryPathInArchive != null) - { - //string s = SharedUtilities.NormalizePath(Path.Combine(directoryPathInArchive, Path.GetDirectoryName(f))); - string s = Path.GetFullPath(Path.Combine(directoryPathInArchive, Path.GetDirectoryName(f))); - this.AddFile(f, s); - } - else - this.AddFile(f, null); - } - } - else - { - foreach (var f in fileNames) - { - if (_addOperationCanceled) break; - this.AddFile(f, directoryPathInArchive); - } - } - if (!_addOperationCanceled) - OnAddCompleted(); - } - - - /// - /// Adds or updates a set of files to the ZipFile, using the specified - /// directory path in the archive. - /// - /// - /// - /// - /// - /// Any files that already exist in the archive are updated. Any files that - /// don't yet exist in the archive are added. - /// - /// - /// - /// For ZipFile properties including , , , , , - /// , and , their - /// respective values at the time of this call will be applied to each - /// ZipEntry added. - /// - /// - /// - /// - /// The names of the files to add or update. Each string should refer to a - /// file in the filesystem. The name of the file may be a relative path or a - /// fully-qualified path. - /// - /// - /// - /// Specifies a directory path to use to override any path in the file name. - /// This path may, or may not, correspond to a real directory in the current - /// filesystem. If the files within the zip are later extracted, this is the - /// path used for the extracted file. Passing null (Nothing in - /// VB) will use the path on each of the fileNames, if any. Passing - /// the empty string ("") will insert the item at the root path within the - /// archive. - /// - /// - /// - public void UpdateFiles(System.Collections.Generic.IEnumerable fileNames, String directoryPathInArchive) - { - if (fileNames == null) - throw new ArgumentNullException("fileNames"); - - OnAddStarted(); - foreach (var f in fileNames) - this.UpdateFile(f, directoryPathInArchive); - OnAddCompleted(); - } - - - - - /// - /// Adds or Updates a File in a Zip file archive. - /// - /// - /// - /// - /// This method adds a file to a zip archive, or, if the file already exists - /// in the zip archive, this method Updates the content of that given filename - /// in the zip archive. The UpdateFile method might more accurately be - /// called "AddOrUpdateFile". - /// - /// - /// - /// Upon success, there is no way for the application to learn whether the file - /// was added versus updated. - /// - /// - /// - /// For ZipFile properties including , , , , , - /// , and , their - /// respective values at the time of this call will be applied to the - /// ZipEntry added. - /// - /// - /// - /// - /// - /// This example shows how to Update an existing entry in a zipfile. The first - /// call to UpdateFile adds the file to the newly-created zip archive. The - /// second call to UpdateFile updates the content for that file in the zip - /// archive. - /// - /// - /// using (ZipFile zip1 = new ZipFile()) - /// { - /// // UpdateFile might more accurately be called "AddOrUpdateFile" - /// zip1.UpdateFile("MyDocuments\\Readme.txt"); - /// zip1.UpdateFile("CustomerList.csv"); - /// zip1.Comment = "This zip archive has been created."; - /// zip1.Save("Content.zip"); - /// } - /// - /// using (ZipFile zip2 = ZipFile.Read("Content.zip")) - /// { - /// zip2.UpdateFile("Updates\\Readme.txt"); - /// zip2.Comment = "This zip archive has been updated: The Readme.txt file has been changed."; - /// zip2.Save(); - /// } - /// - /// - /// - /// Using zip1 As New ZipFile - /// ' UpdateFile might more accurately be called "AddOrUpdateFile" - /// zip1.UpdateFile("MyDocuments\Readme.txt") - /// zip1.UpdateFile("CustomerList.csv") - /// zip1.Comment = "This zip archive has been created." - /// zip1.Save("Content.zip") - /// End Using - /// - /// Using zip2 As ZipFile = ZipFile.Read("Content.zip") - /// zip2.UpdateFile("Updates\Readme.txt") - /// zip2.Comment = "This zip archive has been updated: The Readme.txt file has been changed." - /// zip2.Save - /// End Using - /// - /// - /// - /// - /// - /// - /// - /// - /// The name of the file to add or update. It should refer to a file in the - /// filesystem. The name of the file may be a relative path or a - /// fully-qualified path. - /// - /// - /// - /// The ZipEntry corresponding to the File that was added or updated. - /// - public ZipEntry UpdateFile(string fileName) - { - return UpdateFile(fileName, null); - } - - - - /// - /// Adds or Updates a File in a Zip file archive. - /// - /// - /// - /// - /// This method adds a file to a zip archive, or, if the file already exists - /// in the zip archive, this method Updates the content of that given filename - /// in the zip archive. - /// - /// - /// - /// This version of the method allows the caller to explicitly specify the - /// directory path to be used in the archive. The entry to be added or - /// updated is found by using the specified directory path, combined with the - /// basename of the specified filename. - /// - /// - /// - /// Upon success, there is no way for the application to learn if the file was - /// added versus updated. - /// - /// - /// - /// For ZipFile properties including , , , , , - /// , and , their - /// respective values at the time of this call will be applied to the - /// ZipEntry added. - /// - /// - /// - /// - /// - /// - /// - /// - /// The name of the file to add or update. It should refer to a file in the - /// filesystem. The name of the file may be a relative path or a - /// fully-qualified path. - /// - /// - /// - /// Specifies a directory path to use to override any path in the - /// fileName. This path may, or may not, correspond to a real - /// directory in the current filesystem. If the files within the zip are - /// later extracted, this is the path used for the extracted file. Passing - /// null (Nothing in VB) will use the path on the - /// fileName, if any. Passing the empty string ("") will insert the - /// item at the root path within the archive. - /// - /// - /// - /// The ZipEntry corresponding to the File that was added or updated. - /// - public ZipEntry UpdateFile(string fileName, String directoryPathInArchive) - { - // ideally this would all be transactional! - var key = ZipEntry.NameInArchive(fileName, directoryPathInArchive); - if (this[key] != null) - this.RemoveEntry(key); - return this.AddFile(fileName, directoryPathInArchive); - } - - - - - - /// - /// Add or update a directory in a zip archive. - /// - /// - /// - /// If the specified directory does not exist in the archive, then this method - /// is equivalent to calling AddDirectory(). If the specified - /// directory already exists in the archive, then this method updates any - /// existing entries, and adds any new entries. Any entries that are in the - /// zip archive but not in the specified directory, are left alone. In other - /// words, the contents of the zip file will be a union of the previous - /// contents and the new files. - /// - /// - /// - /// - /// - /// - /// - /// The path to the directory to be added to the zip archive, or updated in - /// the zip archive. - /// - /// - /// - /// The ZipEntry corresponding to the Directory that was added or updated. - /// - public ZipEntry UpdateDirectory(string directoryName) - { - return UpdateDirectory(directoryName, null); - } - - - /// - /// Add or update a directory in the zip archive at the specified root - /// directory in the archive. - /// - /// - /// - /// If the specified directory does not exist in the archive, then this method - /// is equivalent to calling AddDirectory(). If the specified - /// directory already exists in the archive, then this method updates any - /// existing entries, and adds any new entries. Any entries that are in the - /// zip archive but not in the specified directory, are left alone. In other - /// words, the contents of the zip file will be a union of the previous - /// contents and the new files. - /// - /// - /// - /// - /// - /// - /// - /// The path to the directory to be added to the zip archive, or updated - /// in the zip archive. - /// - /// - /// - /// Specifies a directory path to use to override any path in the - /// directoryName. This path may, or may not, correspond to a real - /// directory in the current filesystem. If the files within the zip are - /// later extracted, this is the path used for the extracted file. Passing - /// null (Nothing in VB) will use the path on the - /// directoryName, if any. Passing the empty string ("") will insert - /// the item at the root path within the archive. - /// - /// - /// - /// The ZipEntry corresponding to the Directory that was added or updated. - /// - public ZipEntry UpdateDirectory(string directoryName, String directoryPathInArchive) - { - return this.AddOrUpdateDirectoryImpl(directoryName, directoryPathInArchive, AddOrUpdateAction.AddOrUpdate); - } - - - - - - /// - /// Add or update a file or directory in the zip archive. - /// - /// - /// - /// - /// This is useful when the application is not sure or does not care if the - /// item to be added is a file or directory, and does not know or does not - /// care if the item already exists in the ZipFile. Calling this method - /// is equivalent to calling RemoveEntry() if an entry by the same name - /// already exists, followed calling by AddItem(). - /// - /// - /// - /// For ZipFile properties including , , , , , - /// , and , their - /// respective values at the time of this call will be applied to the - /// ZipEntry added. - /// - /// - /// - /// - /// - /// - /// - /// - /// the path to the file or directory to be added or updated. - /// - public void UpdateItem(string itemName) - { - UpdateItem(itemName, null); - } - - - /// - /// Add or update a file or directory. - /// - /// - /// - /// - /// This method is useful when the application is not sure or does not care if - /// the item to be added is a file or directory, and does not know or does not - /// care if the item already exists in the ZipFile. Calling this method - /// is equivalent to calling RemoveEntry(), if an entry by that name - /// exists, and then calling AddItem(). - /// - /// - /// - /// This version of the method allows the caller to explicitly specify the - /// directory path to be used for the item being added to the archive. The - /// entry or entries that are added or updated will use the specified - /// DirectoryPathInArchive. Extracting the entry from the archive will - /// result in a file stored in that directory path. - /// - /// - /// - /// For ZipFile properties including , , , , , - /// , and , their - /// respective values at the time of this call will be applied to the - /// ZipEntry added. - /// - /// - /// - /// - /// - /// - /// - /// - /// The path for the File or Directory to be added or updated. - /// - /// - /// Specifies a directory path to use to override any path in the - /// itemName. This path may, or may not, correspond to a real - /// directory in the current filesystem. If the files within the zip are - /// later extracted, this is the path used for the extracted file. Passing - /// null (Nothing in VB) will use the path on the - /// itemName, if any. Passing the empty string ("") will insert the - /// item at the root path within the archive. - /// - public void UpdateItem(string itemName, string directoryPathInArchive) - { - if (File.Exists(itemName)) - UpdateFile(itemName, directoryPathInArchive); - - else if (Directory.Exists(itemName)) - UpdateDirectory(itemName, directoryPathInArchive); - - else - throw new FileNotFoundException(String.Format("That file or directory ({0}) does not exist!", itemName)); - } - - - - - /// - /// Adds a named entry into the zip archive, taking content for the entry - /// from a string. - /// - /// - /// - /// Calling this method creates an entry using the given fileName and - /// directory path within the archive. There is no need for a file by the - /// given name to exist in the filesystem; the name is used within the zip - /// archive only. The content for the entry is encoded using the default text - /// encoding for the machine, or on Silverlight, using UTF-8. - /// - /// - /// - /// The content of the file, should it be extracted from the zip. - /// - /// - /// - /// The name, including any path, to use for the entry within the archive. - /// - /// - /// The ZipEntry added. - /// - /// - /// - /// This example shows how to add an entry to the zipfile, using a string as - /// content for that entry. - /// - /// - /// string Content = "This string will be the content of the Readme.txt file in the zip archive."; - /// using (ZipFile zip1 = new ZipFile()) - /// { - /// zip1.AddFile("MyDocuments\\Resume.doc", "files"); - /// zip1.AddEntry("Readme.txt", Content); - /// zip1.Comment = "This zip file was created at " + System.DateTime.Now.ToString("G"); - /// zip1.Save("Content.zip"); - /// } - /// - /// - /// - /// Public Sub Run() - /// Dim Content As String = "This string will be the content of the Readme.txt file in the zip archive." - /// Using zip1 As ZipFile = New ZipFile - /// zip1.AddEntry("Readme.txt", Content) - /// zip1.AddFile("MyDocuments\Resume.doc", "files") - /// zip1.Comment = ("This zip file was created at " & DateTime.Now.ToString("G")) - /// zip1.Save("Content.zip") - /// End Using - /// End Sub - /// - /// - public ZipEntry AddEntry(string entryName, string content) - { -#if SILVERLIGHT - return AddEntry(entryName, content, System.Text.Encoding.UTF8); -#else - return AddEntry(entryName, content, System.Text.Encoding.Default); -#endif - } - - - - /// - /// Adds a named entry into the zip archive, taking content for the entry - /// from a string, and using the specified text encoding. - /// - /// - /// - /// - /// - /// Calling this method creates an entry using the given fileName and - /// directory path within the archive. There is no need for a file by the - /// given name to exist in the filesystem; the name is used within the zip - /// archive only. - /// - /// - /// - /// The content for the entry, a string value, is encoded using the given - /// text encoding. A BOM (byte-order-mark) is emitted into the file, if the - /// Encoding parameter is set for that. - /// - /// - /// - /// Most Encoding classes support a constructor that accepts a boolean, - /// indicating whether to emit a BOM or not. For example see . - /// - /// - /// - /// - /// - /// The name, including any path, to use within the archive for the entry. - /// - /// - /// - /// The content of the file, should it be extracted from the zip. - /// - /// - /// - /// The text encoding to use when encoding the string. Be aware: This is - /// distinct from the text encoding used to encode the fileName, as specified - /// in . - /// - /// - /// The ZipEntry added. - /// - public ZipEntry AddEntry(string entryName, string content, System.Text.Encoding encoding) - { - // cannot employ a using clause here. We need the stream to - // persist after exit from this method. - var ms = new MemoryStream(); - - // cannot use a using clause here; StreamWriter takes - // ownership of the stream and Disposes it before we are ready. - var sw = new StreamWriter(ms, encoding); - sw.Write(content); - sw.Flush(); - - // reset to allow reading later - ms.Seek(0, SeekOrigin.Begin); - - return AddEntry(entryName, ms); - - // must not dispose the MemoryStream - it will be used later. - } - - - /// - /// Create an entry in the ZipFile using the given Stream - /// as input. The entry will have the given filename. - /// - /// - /// - /// - /// - /// The application should provide an open, readable stream; in this case it - /// will be read during the call to or one of - /// its overloads. - /// - /// - /// - /// The passed stream will be read from its current position. If - /// necessary, callers should set the position in the stream before - /// calling AddEntry(). This might be appropriate when using this method - /// with a MemoryStream, for example. - /// - /// - /// - /// In cases where a large number of streams will be added to the - /// ZipFile, the application may wish to avoid maintaining all of the - /// streams open simultaneously. To handle this situation, the application - /// should use the - /// overload. - /// - /// - /// - /// For ZipFile properties including , , , , , - /// , and , their - /// respective values at the time of this call will be applied to the - /// ZipEntry added. - /// - /// - /// - /// - /// - /// - /// This example adds a single entry to a ZipFile via a Stream. - /// - /// - /// - /// String zipToCreate = "Content.zip"; - /// String fileNameInArchive = "Content-From-Stream.bin"; - /// using (System.IO.Stream streamToRead = MyStreamOpener()) - /// { - /// using (ZipFile zip = new ZipFile()) - /// { - /// ZipEntry entry= zip.AddEntry(fileNameInArchive, streamToRead); - /// zip.AddFile("Readme.txt"); - /// zip.Save(zipToCreate); // the stream is read implicitly here - /// } - /// } - /// - /// - /// - /// Dim zipToCreate As String = "Content.zip" - /// Dim fileNameInArchive As String = "Content-From-Stream.bin" - /// Using streamToRead as System.IO.Stream = MyStreamOpener() - /// Using zip As ZipFile = New ZipFile() - /// Dim entry as ZipEntry = zip.AddEntry(fileNameInArchive, streamToRead) - /// zip.AddFile("Readme.txt") - /// zip.Save(zipToCreate) '' the stream is read implicitly, here - /// End Using - /// End Using - /// - /// - /// - /// - /// - /// - /// The name, including any path, which is shown in the zip file for the added - /// entry. - /// - /// - /// The input stream from which to grab content for the file - /// - /// The ZipEntry added. - public ZipEntry AddEntry(string entryName, Stream stream) - { - ZipEntry ze = ZipEntry.CreateForStream(entryName, stream); - ze.SetEntryTimes(DateTime.Now,DateTime.Now,DateTime.Now); - if (Verbose) StatusMessageTextWriter.WriteLine("adding {0}...", entryName); - return _InternalAddEntry(ze); - } - - - - /// - /// Add a ZipEntry for which content is written directly by the application. - /// - /// - /// - /// - /// When the application needs to write the zip entry data, use this - /// method to add the ZipEntry. For example, in the case that the - /// application wishes to write the XML representation of a DataSet into - /// a ZipEntry, the application can use this method to do so. - /// - /// - /// - /// For ZipFile properties including , , , , , - /// , and , their - /// respective values at the time of this call will be applied to the - /// ZipEntry added. - /// - /// - /// - /// About progress events: When using the WriteDelegate, DotNetZip does - /// not issue any SaveProgress events with EventType = - /// Saving_EntryBytesRead. (This is because it is the - /// application's code that runs in WriteDelegate - there's no way for - /// DotNetZip to know when to issue a EntryBytesRead event.) - /// Applications that want to update a progress bar or similar status - /// indicator should do so from within the WriteDelegate - /// itself. DotNetZip will issue the other SaveProgress events, - /// including - /// Saving_Started, - /// - /// Saving_BeforeWriteEntry, and - /// Saving_AfterWriteEntry. - /// - /// - /// - /// Note: When you use PKZip encryption, it's normally necessary to - /// compute the CRC of the content to be encrypted, before compressing or - /// encrypting it. Therefore, when using PKZip encryption with a - /// WriteDelegate, the WriteDelegate CAN BE called twice: once to compute - /// the CRC, and the second time to potentially compress and - /// encrypt. Surprising, but true. This is because PKWARE specified that - /// the encryption initialization data depends on the CRC. - /// If this happens, for each call of the delegate, your - /// application must stream the same entry data in its entirety. If your - /// application writes different data during the second call, it will - /// result in a corrupt zip file. - /// - /// - /// - /// The double-read behavior happens with all types of entries, not only - /// those that use WriteDelegate. It happens if you add an entry from a - /// filesystem file, or using a string, or a stream, or an opener/closer - /// pair. But in those cases, DotNetZip takes care of reading twice; in - /// the case of the WriteDelegate, the application code gets invoked - /// twice. Be aware. - /// - /// - /// - /// As you can imagine, this can cause performance problems for large - /// streams, and it can lead to correctness problems when you use a - /// WriteDelegate. This is a pretty big pitfall. There are two - /// ways to avoid it. First, and most preferred: don't use PKZIP - /// encryption. If you use the WinZip AES encryption, this problem - /// doesn't occur, because the encryption protocol doesn't require the CRC - /// up front. Second: if you do choose to use PKZIP encryption, write out - /// to a non-seekable stream (like standard output, or the - /// Response.OutputStream in an ASP.NET application). In this case, - /// DotNetZip will use an alternative encryption protocol that does not - /// rely on the CRC of the content. This also implies setting bit 3 in - /// the zip entry, which still presents problems for some zip tools. - /// - /// - /// - /// In the future I may modify DotNetZip to *always* use bit 3 when PKZIP - /// encryption is in use. This seems like a win overall, but there will - /// be some work involved. If you feel strongly about it, visit the - /// DotNetZip forums and vote up the Workitem - /// tracking this issue. - /// - /// - /// - /// - /// the name of the entry to add - /// the delegate which will write the entry content - /// the ZipEntry added - /// - /// - /// - /// This example shows an application filling a DataSet, then saving the - /// contents of that DataSet as XML, into a ZipEntry in a ZipFile, using an - /// anonymous delegate in C#. The DataSet XML is never saved to a disk file. - /// - /// - /// var c1= new System.Data.SqlClient.SqlConnection(connstring1); - /// var da = new System.Data.SqlClient.SqlDataAdapter() - /// { - /// SelectCommand= new System.Data.SqlClient.SqlCommand(strSelect, c1) - /// }; - /// - /// DataSet ds1 = new DataSet(); - /// da.Fill(ds1, "Invoices"); - /// - /// using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile()) - /// { - /// zip.AddEntry(zipEntryName, (name,stream) => ds1.WriteXml(stream) ); - /// zip.Save(zipFileName); - /// } - /// - /// - /// - /// - /// - /// This example uses an anonymous method in C# as the WriteDelegate to provide - /// the data for the ZipEntry. The example is a bit contrived - the - /// AddFile() method is a simpler way to insert the contents of a file - /// into an entry in a zip file. On the other hand, if there is some sort of - /// processing or transformation of the file contents required before writing, - /// the application could use the WriteDelegate to do it, in this way. - /// - /// - /// using (var input = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite )) - /// { - /// using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile()) - /// { - /// zip.AddEntry(zipEntryName, (name,output) => - /// { - /// byte[] buffer = new byte[BufferSize]; - /// int n; - /// while ((n = input.Read(buffer, 0, buffer.Length)) != 0) - /// { - /// // could transform the data here... - /// output.Write(buffer, 0, n); - /// // could update a progress bar here - /// } - /// }); - /// - /// zip.Save(zipFileName); - /// } - /// } - /// - /// - /// - /// - /// - /// This example uses a named delegate in VB to write data for the given - /// ZipEntry (VB9 does not have anonymous delegates). The example here is a bit - /// contrived - a simpler way to add the contents of a file to a ZipEntry is to - /// simply use the appropriate AddFile() method. The key scenario for - /// which the WriteDelegate makes sense is saving a DataSet, in XML - /// format, to the zip file. The DataSet can write XML to a stream, and the - /// WriteDelegate is the perfect place to write into the zip file. There may be - /// other data structures that can write to a stream, but cannot be read as a - /// stream. The WriteDelegate would be appropriate for those cases as - /// well. - /// - /// - /// Private Sub WriteEntry (ByVal name As String, ByVal output As Stream) - /// Using input As FileStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) - /// Dim n As Integer = -1 - /// Dim buffer As Byte() = New Byte(BufferSize){} - /// Do While n <> 0 - /// n = input.Read(buffer, 0, buffer.Length) - /// output.Write(buffer, 0, n) - /// Loop - /// End Using - /// End Sub - /// - /// Public Sub Run() - /// Using zip = New ZipFile - /// zip.AddEntry(zipEntryName, New WriteDelegate(AddressOf WriteEntry)) - /// zip.Save(zipFileName) - /// End Using - /// End Sub - /// - /// - public ZipEntry AddEntry(string entryName, WriteDelegate writer) - { - ZipEntry ze = ZipEntry.CreateForWriter(entryName, writer); - if (Verbose) StatusMessageTextWriter.WriteLine("adding {0}...", entryName); - return _InternalAddEntry(ze); - } - - - /// - /// Add an entry, for which the application will provide a stream - /// containing the entry data, on a just-in-time basis. - /// - /// - /// - /// - /// In cases where the application wishes to open the stream that - /// holds the content for the ZipEntry, on a just-in-time basis, the - /// application can use this method. The application provides an - /// opener delegate that will be called by the DotNetZip library to - /// obtain a readable stream that can be read to get the bytes for - /// the given entry. Typically, this delegate opens a stream. - /// Optionally, the application can provide a closer delegate as - /// well, which will be called by DotNetZip when all bytes have been - /// read from the entry. - /// - /// - /// - /// These delegates are called from within the scope of the call to - /// ZipFile.Save(). - /// - /// - /// - /// For ZipFile properties including , , , , , - /// , and , their - /// respective values at the time of this call will be applied to the - /// ZipEntry added. - /// - /// - /// - /// - /// - /// - /// This example uses anonymous methods in C# to open and close the - /// source stream for the content for a zip entry. - /// - /// - /// using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile()) - /// { - /// zip.AddEntry(zipEntryName, - /// (name) => File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ), - /// (name, stream) => stream.Close() - /// ); - /// - /// zip.Save(zipFileName); - /// } - /// - /// - /// - /// - /// - /// - /// This example uses delegates in VB.NET to open and close the - /// the source stream for the content for a zip entry. VB 9.0 lacks - /// support for "Sub" lambda expressions, and so the CloseDelegate must - /// be an actual, named Sub. - /// - /// - /// - /// Function MyStreamOpener(ByVal entryName As String) As Stream - /// '' This simply opens a file. You probably want to do somethinig - /// '' more involved here: open a stream to read from a database, - /// '' open a stream on an HTTP connection, and so on. - /// Return File.OpenRead(entryName) - /// End Function - /// - /// Sub MyStreamCloser(entryName As String, stream As Stream) - /// stream.Close() - /// End Sub - /// - /// Public Sub Run() - /// Dim dirToZip As String = "fodder" - /// Dim zipFileToCreate As String = "Archive.zip" - /// Dim opener As OpenDelegate = AddressOf MyStreamOpener - /// Dim closer As CloseDelegate = AddressOf MyStreamCloser - /// Dim numFilestoAdd As Int32 = 4 - /// Using zip As ZipFile = New ZipFile - /// Dim i As Integer - /// For i = 0 To numFilesToAdd - 1 - /// zip.AddEntry(String.Format("content-{0:000}.txt"), opener, closer) - /// Next i - /// zip.Save(zipFileToCreate) - /// End Using - /// End Sub - /// - /// - /// - /// - /// the name of the entry to add - /// - /// the delegate that will be invoked by ZipFile.Save() to get the - /// readable stream for the given entry. ZipFile.Save() will call - /// read on this stream to obtain the data for the entry. This data - /// will then be compressed and written to the newly created zip - /// file. - /// - /// - /// the delegate that will be invoked to close the stream. This may - /// be null (Nothing in VB), in which case no call is makde to close - /// the stream. - /// - /// the ZipEntry added - /// - public ZipEntry AddEntry(string entryName, OpenDelegate opener, CloseDelegate closer) - { - ZipEntry ze = ZipEntry.CreateForJitStreamProvider(entryName, opener, closer); - ze.SetEntryTimes(DateTime.Now,DateTime.Now,DateTime.Now); - if (Verbose) StatusMessageTextWriter.WriteLine("adding {0}...", entryName); - return _InternalAddEntry(ze); - } - - - - private ZipEntry _InternalAddEntry(ZipEntry ze) - { - // stamp all the props onto the entry - ze._container = new ZipContainer(this); - ze.CompressionMethod = this.CompressionMethod; - ze.CompressionLevel = this.CompressionLevel; - ze.ExtractExistingFile = this.ExtractExistingFile; - ze.ZipErrorAction = this.ZipErrorAction; - ze.SetCompression = this.SetCompression; - ze.AlternateEncoding = this.AlternateEncoding; - ze.AlternateEncodingUsage = this.AlternateEncodingUsage; - ze.Password = this._Password; - ze.Encryption = this.Encryption; - ze.EmitTimesInWindowsFormatWhenSaving = this._emitNtfsTimes; - ze.EmitTimesInUnixFormatWhenSaving = this._emitUnixTimes; - //string key = DictionaryKeyForEntry(ze); - InternalAddEntry(ze.FileName,ze); - AfterAddEntry(ze); - return ze; - } - - - - - /// - /// Updates the given entry in the ZipFile, using the given - /// string as content for the ZipEntry. - /// - /// - /// - /// - /// - /// Calling this method is equivalent to removing the ZipEntry for - /// the given file name and directory path, if it exists, and then calling - /// . See the documentation for - /// that method for further explanation. The string content is encoded - /// using the default encoding for the machine, or on Silverlight, using - /// UTF-8. This encoding is distinct from the encoding used for the - /// filename itself. See . - /// - /// - /// - /// - /// - /// The name, including any path, to use within the archive for the entry. - /// - /// - /// - /// The content of the file, should it be extracted from the zip. - /// - /// - /// The ZipEntry added. - /// - public ZipEntry UpdateEntry(string entryName, string content) - { -#if SILVERLIGHT - return UpdateEntry(entryName, content, System.Text.Encoding.UTF8); -#else - return UpdateEntry(entryName, content, System.Text.Encoding.Default); -#endif - } - - - /// - /// Updates the given entry in the ZipFile, using the given string as - /// content for the ZipEntry. - /// - /// - /// - /// Calling this method is equivalent to removing the ZipEntry for the - /// given file name and directory path, if it exists, and then calling . See the - /// documentation for that method for further explanation. - /// - /// - /// - /// The name, including any path, to use within the archive for the entry. - /// - /// - /// - /// The content of the file, should it be extracted from the zip. - /// - /// - /// - /// The text encoding to use when encoding the string. Be aware: This is - /// distinct from the text encoding used to encode the filename. See . - /// - /// - /// The ZipEntry added. - /// - public ZipEntry UpdateEntry(string entryName, string content, System.Text.Encoding encoding) - { - RemoveEntryForUpdate(entryName); - return AddEntry(entryName, content, encoding); - } - - - - /// - /// Updates the given entry in the ZipFile, using the given delegate - /// as the source for content for the ZipEntry. - /// - /// - /// - /// Calling this method is equivalent to removing the ZipEntry for the - /// given file name and directory path, if it exists, and then calling . See the - /// documentation for that method for further explanation. - /// - /// - /// - /// The name, including any path, to use within the archive for the entry. - /// - /// - /// the delegate which will write the entry content. - /// - /// The ZipEntry added. - /// - public ZipEntry UpdateEntry(string entryName, WriteDelegate writer) - { - RemoveEntryForUpdate(entryName); - return AddEntry(entryName, writer); - } - - - - /// - /// Updates the given entry in the ZipFile, using the given delegates - /// to open and close the stream that provides the content for the ZipEntry. - /// - /// - /// - /// Calling this method is equivalent to removing the ZipEntry for the - /// given file name and directory path, if it exists, and then calling . See the - /// documentation for that method for further explanation. - /// - /// - /// - /// The name, including any path, to use within the archive for the entry. - /// - /// - /// - /// the delegate that will be invoked to open the stream - /// - /// - /// the delegate that will be invoked to close the stream - /// - /// - /// The ZipEntry added or updated. - /// - public ZipEntry UpdateEntry(string entryName, OpenDelegate opener, CloseDelegate closer) - { - RemoveEntryForUpdate(entryName); - return AddEntry(entryName, opener, closer); - } - - - /// - /// Updates the given entry in the ZipFile, using the given stream as - /// input, and the given filename and given directory Path. - /// - /// - /// - /// - /// Calling the method is equivalent to calling RemoveEntry() if an - /// entry by the same name already exists, and then calling AddEntry() - /// with the given fileName and stream. - /// - /// - /// - /// The stream must be open and readable during the call to - /// ZipFile.Save. You can dispense the stream on a just-in-time basis - /// using the property. Check the - /// documentation of that property for more information. - /// - /// - /// - /// For ZipFile properties including , , , , , - /// , and , their - /// respective values at the time of this call will be applied to the - /// ZipEntry added. - /// - /// - /// - /// - /// - /// - /// - /// - /// The name, including any path, to use within the archive for the entry. - /// - /// - /// The input stream from which to read file data. - /// The ZipEntry added. - public ZipEntry UpdateEntry(string entryName, Stream stream) - { - RemoveEntryForUpdate(entryName); - return AddEntry(entryName, stream); - } - - - private void RemoveEntryForUpdate(string entryName) - { - if (String.IsNullOrEmpty(entryName)) - throw new ArgumentNullException("entryName"); - - string directoryPathInArchive = null; - if (entryName.IndexOf('\\') != -1) - { - directoryPathInArchive = Path.GetDirectoryName(entryName); - entryName = Path.GetFileName(entryName); - } - var key = ZipEntry.NameInArchive(entryName, directoryPathInArchive); - if (this[key] != null) - this.RemoveEntry(key); - } - - - - - /// - /// Add an entry into the zip archive using the given filename and - /// directory path within the archive, and the given content for the - /// file. No file is created in the filesystem. - /// - /// - /// The data to use for the entry. - /// - /// - /// The name, including any path, to use within the archive for the entry. - /// - /// - /// The ZipEntry added. - public ZipEntry AddEntry(string entryName, byte[] byteContent) - { - if (byteContent == null) throw new ArgumentException("bad argument", "byteContent"); - var ms = new MemoryStream(byteContent); - return AddEntry(entryName, ms); - } - - - /// - /// Updates the given entry in the ZipFile, using the given byte - /// array as content for the entry. - /// - /// - /// - /// Calling this method is equivalent to removing the ZipEntry - /// for the given filename and directory path, if it exists, and then - /// calling . See the - /// documentation for that method for further explanation. - /// - /// - /// - /// The name, including any path, to use within the archive for the entry. - /// - /// - /// The content to use for the ZipEntry. - /// - /// The ZipEntry added. - /// - public ZipEntry UpdateEntry(string entryName, byte[] byteContent) - { - RemoveEntryForUpdate(entryName); - return AddEntry(entryName, byteContent); - } - - -// private string DictionaryKeyForEntry(ZipEntry ze1) -// { -// var filename = SharedUtilities.NormalizePathForUseInZipFile(ze1.FileName); -// return filename; -// } - - - /// - /// Adds the contents of a filesystem directory to a Zip file archive. - /// - /// - /// - /// - /// - /// The name of the directory may be a relative path or a fully-qualified - /// path. Any files within the named directory are added to the archive. Any - /// subdirectories within the named directory are also added to the archive, - /// recursively. - /// - /// - /// - /// Top-level entries in the named directory will appear as top-level entries - /// in the zip archive. Entries in subdirectories in the named directory will - /// result in entries in subdirectories in the zip archive. - /// - /// - /// - /// If you want the entries to appear in a containing directory in the zip - /// archive itself, then you should call the AddDirectory() overload that - /// allows you to explicitly specify a directory path for use in the archive. - /// - /// - /// - /// For ZipFile properties including , , , , , - /// , and , their - /// respective values at the time of this call will be applied to each - /// ZipEntry added. - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// This method has 2 overloads. - /// - /// The name of the directory to add. - /// The ZipEntry added. - public ZipEntry AddDirectory(string directoryName) - { - return AddDirectory(directoryName, null); - } - - - /// - /// Adds the contents of a filesystem directory to a Zip file archive, - /// overriding the path to be used for entries in the archive. - /// - /// - /// - /// - /// The name of the directory may be a relative path or a fully-qualified - /// path. The add operation is recursive, so that any files or subdirectories - /// within the name directory are also added to the archive. - /// - /// - /// - /// Top-level entries in the named directory will appear as top-level entries - /// in the zip archive. Entries in subdirectories in the named directory will - /// result in entries in subdirectories in the zip archive. - /// - /// - /// - /// For ZipFile properties including , , , , , - /// , and , their - /// respective values at the time of this call will be applied to each - /// ZipEntry added. - /// - /// - /// - /// - /// - /// - /// In this code, calling the ZipUp() method with a value of "c:\reports" for - /// the directory parameter will result in a zip file structure in which all - /// entries are contained in a toplevel "reports" directory. - /// - /// - /// - /// public void ZipUp(string targetZip, string directory) - /// { - /// using (var zip = new ZipFile()) - /// { - /// zip.AddDirectory(directory, System.IO.Path.GetFileName(directory)); - /// zip.Save(targetZip); - /// } - /// } - /// - /// - /// - /// - /// - /// - /// - /// The name of the directory to add. - /// - /// - /// Specifies a directory path to use to override any path in the - /// DirectoryName. This path may, or may not, correspond to a real directory - /// in the current filesystem. If the zip is later extracted, this is the - /// path used for the extracted file or directory. Passing null - /// (Nothing in VB) or the empty string ("") will insert the items at - /// the root path within the archive. - /// - /// - /// The ZipEntry added. - public ZipEntry AddDirectory(string directoryName, string directoryPathInArchive) - { - return AddOrUpdateDirectoryImpl(directoryName, directoryPathInArchive, AddOrUpdateAction.AddOnly); - } - - - /// - /// Creates a directory in the zip archive. - /// - /// - /// - /// - /// - /// Use this when you want to create a directory in the archive but there is - /// no corresponding filesystem representation for that directory. - /// - /// - /// - /// You will probably not need to do this in your code. One of the only times - /// you will want to do this is if you want an empty directory in the zip - /// archive. The reason: if you add a file to a zip archive that is stored - /// within a multi-level directory, all of the directory tree is implicitly - /// created in the zip archive. - /// - /// - /// - /// - /// - /// The name of the directory to create in the archive. - /// - /// The ZipEntry added. - public ZipEntry AddDirectoryByName(string directoryNameInArchive) - { - // workitem 9073 - ZipEntry dir = ZipEntry.CreateFromNothing(directoryNameInArchive); - dir._container = new ZipContainer(this); - dir.MarkAsDirectory(); - dir.AlternateEncoding = this.AlternateEncoding; // workitem 8984 - dir.AlternateEncodingUsage = this.AlternateEncodingUsage; - dir.SetEntryTimes(DateTime.Now,DateTime.Now,DateTime.Now); - dir.EmitTimesInWindowsFormatWhenSaving = _emitNtfsTimes; - dir.EmitTimesInUnixFormatWhenSaving = _emitUnixTimes; - dir._Source = ZipEntrySource.Stream; - //string key = DictionaryKeyForEntry(dir); - InternalAddEntry(dir.FileName,dir); - AfterAddEntry(dir); - return dir; - } - - - - private ZipEntry AddOrUpdateDirectoryImpl(string directoryName, - string rootDirectoryPathInArchive, - AddOrUpdateAction action) - { - if (rootDirectoryPathInArchive == null) - { - rootDirectoryPathInArchive = ""; - } - - return AddOrUpdateDirectoryImpl(directoryName, rootDirectoryPathInArchive, action, true, 0); - } - - - internal void InternalAddEntry(String name, ZipEntry entry) - { - _entries.Add(name, entry); - _zipEntriesAsList = null; - _contentsChanged = true; - } - - - - private ZipEntry AddOrUpdateDirectoryImpl(string directoryName, - string rootDirectoryPathInArchive, - AddOrUpdateAction action, - bool recurse, - int level) - { - if (Verbose) - StatusMessageTextWriter.WriteLine("{0} {1}...", - (action == AddOrUpdateAction.AddOnly) ? "adding" : "Adding or updating", - directoryName); - - if (level == 0) - { - _addOperationCanceled = false; - OnAddStarted(); - } - - // workitem 13371 - if (_addOperationCanceled) - return null; - - string dirForEntries = rootDirectoryPathInArchive; - ZipEntry baseDir = null; - - if (level > 0) - { - int f = directoryName.Length; - for (int i = level; i > 0; i--) - f = directoryName.LastIndexOfAny("/\\".ToCharArray(), f - 1, f - 1); - - dirForEntries = directoryName.Substring(f + 1); - dirForEntries = Path.Combine(rootDirectoryPathInArchive, dirForEntries); - } - - // if not top level, or if the root is non-empty, then explicitly add the directory - if (level > 0 || rootDirectoryPathInArchive != "") - { - baseDir = ZipEntry.CreateFromFile(directoryName, dirForEntries); - baseDir._container = new ZipContainer(this); - baseDir.AlternateEncoding = this.AlternateEncoding; // workitem 6410 - baseDir.AlternateEncodingUsage = this.AlternateEncodingUsage; - baseDir.MarkAsDirectory(); - baseDir.EmitTimesInWindowsFormatWhenSaving = _emitNtfsTimes; - baseDir.EmitTimesInUnixFormatWhenSaving = _emitUnixTimes; - - // add the directory only if it does not exist. - // It's not an error if it already exists. - if (!_entries.ContainsKey(baseDir.FileName)) - { - InternalAddEntry(baseDir.FileName,baseDir); - AfterAddEntry(baseDir); - } - dirForEntries = baseDir.FileName; - } - - if (!_addOperationCanceled) - { - - String[] filenames = Directory.GetFiles(directoryName); - - if (recurse) - { - // add the files: - foreach (String filename in filenames) - { - if (_addOperationCanceled) break; - if (action == AddOrUpdateAction.AddOnly) - AddFile(filename, dirForEntries); - else - UpdateFile(filename, dirForEntries); - } - - if (!_addOperationCanceled) - { - // add the subdirectories: - String[] dirnames = Directory.GetDirectories(directoryName); - foreach (String dir in dirnames) - { - // workitem 8617: Optionally traverse reparse points -#if SILVERLIGHT -#elif NETCF - FileAttributes fileAttrs = (FileAttributes) NetCfFile.GetAttributes(dir); -#else - FileAttributes fileAttrs = System.IO.File.GetAttributes(dir); -#endif - if (this.AddDirectoryWillTraverseReparsePoints -#if !SILVERLIGHT - || ((fileAttrs & FileAttributes.ReparsePoint) == 0) -#endif - ) - AddOrUpdateDirectoryImpl(dir, rootDirectoryPathInArchive, action, recurse, level + 1); - - } - - } - } - } - - if (level == 0) - OnAddCompleted(); - - return baseDir; - } - - } - -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Check.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Check.cs deleted file mode 100644 index b8307d50..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Check.cs +++ /dev/null @@ -1,352 +0,0 @@ -// 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 - { - /// - /// Checks a zip file to see if its directory is consistent. - /// - /// - /// - /// - /// - /// 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. - /// - /// - /// This method may take a long time to run for large zip files. - /// - /// - /// This method is not supported in the Reduced or Compact Framework - /// versions of DotNetZip. - /// - /// - /// - /// Developers using COM can use the ComHelper.CheckZip(String) - /// method. - /// - /// - /// - /// - /// The filename to of the zip file to check. - /// - /// true if the named zip file checks OK. Otherwise, false. - /// - /// - /// - public static bool CheckZip(string zipFileName) - { - return CheckZip(zipFileName, false, null); - } - - - /// - /// Checks a zip file to see if its directory is consistent, - /// and optionally fixes the directory if necessary. - /// - /// - /// - /// - /// - /// 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 Name_Fixed.zip. - /// - /// - /// - /// 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 - /// fixIfNecessary is true. - /// - /// - /// - /// This method is not supported in the Reduced or Compact - /// Framework versions of DotNetZip. - /// - /// - /// - /// - /// The filename to of the zip file to check. - /// - /// If true, the method will fix the zip file if - /// necessary. - /// - /// - /// a TextWriter in which messages generated while checking will be written. - /// - /// - /// true if the named zip is OK; false if the file needs to be fixed. - /// - /// - /// - 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; - } - - - - /// - /// Rewrite the directory within a zipfile. - /// - /// - /// - /// - /// - /// 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. - /// - /// - /// This can take a long time for large zip files. - /// - /// This won't work if the zip file uses a non-standard - /// code page - neither IBM437 nor UTF-8. - /// - /// - /// This method is not supported in the Reduced or Compact Framework - /// versions of DotNetZip. - /// - /// - /// - /// Developers using COM can use the ComHelper.FixZipDirectory(String) - /// method. - /// - /// - /// - /// - /// The filename to of the zip file to fix. - /// - /// - /// - public static void FixZipDirectory(string zipFileName) - { - using (var zip = new ZipFile()) - { - zip.FullScan = true; - zip.Initialize(zipFileName); - zip.Save(zipFileName); - } - } - - - - /// - /// Verify the password on a zip file. - /// - /// - /// - /// - /// 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. - /// - /// - /// There is no way to check a password without doing the - /// decryption. So this code decrypts and extracts the given - /// zipfile into - /// - /// - /// - /// The filename to of the zip file to fix. - /// - /// The password to check. - /// - /// a bool indicating whether the password matches. - 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; - } - - - /// - /// Provides a human-readable string with information about the ZipFile. - /// - /// - /// - /// - /// 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. - /// - /// - /// This information is mostly useful for diagnostic purposes. - /// - /// - 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(); - } - } - - - } - -} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Events.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Events.cs deleted file mode 100644 index 110ee6d1..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Events.cs +++ /dev/null @@ -1,1219 +0,0 @@ -// ZipFile.Events.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2008, 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-09 08:42:35> -// -// ------------------------------------------------------------------ -// -// This module defines the methods for issuing events from the ZipFile class. -// -// ------------------------------------------------------------------ -// - -using System; -using System.IO; - -namespace Ionic.Zip -{ - public partial class ZipFile - { - private string ArchiveNameForEvent - { - get - { - return (_name != null) ? _name : "(stream)"; - } - } - - #region Save - - /// - /// An event handler invoked when a Save() starts, before and after each - /// entry has been written to the archive, when a Save() completes, and - /// during other Save events. - /// - /// - /// - /// - /// Depending on the particular event, different properties on the parameter are set. The following - /// table summarizes the available EventTypes and the conditions under - /// which this event handler is invoked with a - /// SaveProgressEventArgs with the given EventType. - /// - /// - /// - /// - /// value of EntryType - /// Meaning and conditions - /// - /// - /// - /// ZipProgressEventType.Saving_Started - /// Fired when ZipFile.Save() begins. - /// - /// - /// - /// - /// ZipProgressEventType.Saving_BeforeSaveEntry - /// - /// Fired within ZipFile.Save(), just before writing data for each - /// particular entry. - /// - /// - /// - /// - /// ZipProgressEventType.Saving_AfterSaveEntry - /// - /// Fired within ZipFile.Save(), just after having finished writing data - /// for each particular entry. - /// - /// - /// - /// - /// ZipProgressEventType.Saving_Completed - /// Fired when ZipFile.Save() has completed. - /// - /// - /// - /// - /// ZipProgressEventType.Saving_AfterSaveTempArchive - /// - /// Fired after the temporary file has been created. This happens only - /// when saving to a disk file. This event will not be invoked when - /// saving to a stream. - /// - /// - /// - /// - /// ZipProgressEventType.Saving_BeforeRenameTempArchive - /// - /// Fired just before renaming the temporary file to the permanent - /// location. This happens only when saving to a disk file. This event - /// will not be invoked when saving to a stream. - /// - /// - /// - /// - /// ZipProgressEventType.Saving_AfterRenameTempArchive - /// - /// Fired just after renaming the temporary file to the permanent - /// location. This happens only when saving to a disk file. This event - /// will not be invoked when saving to a stream. - /// - /// - /// - /// - /// ZipProgressEventType.Saving_AfterCompileSelfExtractor - /// - /// Fired after a self-extracting archive has finished compiling. This - /// EventType is used only within SaveSelfExtractor(). - /// - /// - /// - /// - /// ZipProgressEventType.Saving_BytesRead - /// - /// Set during the save of a particular entry, to update progress of the - /// Save(). When this EventType is set, the BytesTransferred is the - /// number of bytes that have been read from the source stream. The - /// TotalBytesToTransfer is the number of bytes in the uncompressed - /// file. - /// - /// - /// - /// - /// - /// - /// - /// - /// This example uses an anonymous method to handle the - /// SaveProgress event, by updating a progress bar. - /// - /// - /// progressBar1.Value = 0; - /// progressBar1.Max = listbox1.Items.Count; - /// using (ZipFile zip = new ZipFile()) - /// { - /// // listbox1 contains a list of filenames - /// zip.AddFiles(listbox1.Items); - /// - /// // do the progress bar: - /// zip.SaveProgress += (sender, e) => { - /// if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry) { - /// progressBar1.PerformStep(); - /// } - /// }; - /// - /// zip.Save(fs); - /// } - /// - /// - /// - /// - /// This example uses a named method as the - /// SaveProgress event handler, to update the user, in a - /// console-based application. - /// - /// - /// static bool justHadByteUpdate= false; - /// public static void SaveProgress(object sender, SaveProgressEventArgs e) - /// { - /// if (e.EventType == ZipProgressEventType.Saving_Started) - /// Console.WriteLine("Saving: {0}", e.ArchiveName); - /// - /// else if (e.EventType == ZipProgressEventType.Saving_Completed) - /// { - /// justHadByteUpdate= false; - /// Console.WriteLine(); - /// Console.WriteLine("Done: {0}", e.ArchiveName); - /// } - /// - /// else if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry) - /// { - /// if (justHadByteUpdate) - /// Console.WriteLine(); - /// Console.WriteLine(" Writing: {0} ({1}/{2})", - /// e.CurrentEntry.FileName, e.EntriesSaved, e.EntriesTotal); - /// justHadByteUpdate= false; - /// } - /// - /// else if (e.EventType == ZipProgressEventType.Saving_EntryBytesRead) - /// { - /// if (justHadByteUpdate) - /// Console.SetCursorPosition(0, Console.CursorTop); - /// Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer, - /// e.BytesTransferred / (0.01 * e.TotalBytesToTransfer )); - /// justHadByteUpdate= true; - /// } - /// } - /// - /// public static ZipUp(string targetZip, string directory) - /// { - /// using (var zip = new ZipFile()) { - /// zip.SaveProgress += SaveProgress; - /// zip.AddDirectory(directory); - /// zip.Save(targetZip); - /// } - /// } - /// - /// - /// - /// - /// Public Sub ZipUp(ByVal targetZip As String, ByVal directory As String) - /// Using zip As ZipFile = New ZipFile - /// AddHandler zip.SaveProgress, AddressOf MySaveProgress - /// zip.AddDirectory(directory) - /// zip.Save(targetZip) - /// End Using - /// End Sub - /// - /// Private Shared justHadByteUpdate As Boolean = False - /// - /// Public Shared Sub MySaveProgress(ByVal sender As Object, ByVal e As SaveProgressEventArgs) - /// If (e.EventType Is ZipProgressEventType.Saving_Started) Then - /// Console.WriteLine("Saving: {0}", e.ArchiveName) - /// - /// ElseIf (e.EventType Is ZipProgressEventType.Saving_Completed) Then - /// justHadByteUpdate = False - /// Console.WriteLine - /// Console.WriteLine("Done: {0}", e.ArchiveName) - /// - /// ElseIf (e.EventType Is ZipProgressEventType.Saving_BeforeWriteEntry) Then - /// If justHadByteUpdate Then - /// Console.WriteLine - /// End If - /// Console.WriteLine(" Writing: {0} ({1}/{2})", e.CurrentEntry.FileName, e.EntriesSaved, e.EntriesTotal) - /// justHadByteUpdate = False - /// - /// ElseIf (e.EventType Is ZipProgressEventType.Saving_EntryBytesRead) Then - /// If justHadByteUpdate Then - /// Console.SetCursorPosition(0, Console.CursorTop) - /// End If - /// Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, _ - /// e.TotalBytesToTransfer, _ - /// (CDbl(e.BytesTransferred) / (0.01 * e.TotalBytesToTransfer))) - /// justHadByteUpdate = True - /// End If - /// End Sub - /// - /// - /// - /// - /// - /// This is a more complete example of using the SaveProgress - /// events in a Windows Forms application, with a - /// Thread object. - /// - /// - /// delegate void SaveEntryProgress(SaveProgressEventArgs e); - /// delegate void ButtonClick(object sender, EventArgs e); - /// - /// public class WorkerOptions - /// { - /// public string ZipName; - /// public string Folder; - /// public string Encoding; - /// public string Comment; - /// public int ZipFlavor; - /// public Zip64Option Zip64; - /// } - /// - /// private int _progress2MaxFactor; - /// private bool _saveCanceled; - /// private long _totalBytesBeforeCompress; - /// private long _totalBytesAfterCompress; - /// private Thread _workerThread; - /// - /// - /// private void btnZipup_Click(object sender, EventArgs e) - /// { - /// KickoffZipup(); - /// } - /// - /// private void btnCancel_Click(object sender, EventArgs e) - /// { - /// if (this.lblStatus.InvokeRequired) - /// { - /// this.lblStatus.Invoke(new ButtonClick(this.btnCancel_Click), new object[] { sender, e }); - /// } - /// else - /// { - /// _saveCanceled = true; - /// lblStatus.Text = "Canceled..."; - /// ResetState(); - /// } - /// } - /// - /// private void KickoffZipup() - /// { - /// _folderName = tbDirName.Text; - /// - /// if (_folderName == null || _folderName == "") return; - /// if (this.tbZipName.Text == null || this.tbZipName.Text == "") return; - /// - /// // check for existence of the zip file: - /// if (System.IO.File.Exists(this.tbZipName.Text)) - /// { - /// var dlgResult = MessageBox.Show(String.Format("The file you have specified ({0}) already exists." + - /// " Do you want to overwrite this file?", this.tbZipName.Text), - /// "Confirmation is Required", MessageBoxButtons.YesNo, MessageBoxIcon.Question); - /// if (dlgResult != DialogResult.Yes) return; - /// System.IO.File.Delete(this.tbZipName.Text); - /// } - /// - /// _saveCanceled = false; - /// _nFilesCompleted = 0; - /// _totalBytesAfterCompress = 0; - /// _totalBytesBeforeCompress = 0; - /// this.btnOk.Enabled = false; - /// this.btnOk.Text = "Zipping..."; - /// this.btnCancel.Enabled = true; - /// lblStatus.Text = "Zipping..."; - /// - /// var options = new WorkerOptions - /// { - /// ZipName = this.tbZipName.Text, - /// Folder = _folderName, - /// Encoding = "ibm437" - /// }; - /// - /// if (this.comboBox1.SelectedIndex != 0) - /// { - /// options.Encoding = this.comboBox1.SelectedItem.ToString(); - /// } - /// - /// if (this.radioFlavorSfxCmd.Checked) - /// options.ZipFlavor = 2; - /// else if (this.radioFlavorSfxGui.Checked) - /// options.ZipFlavor = 1; - /// else options.ZipFlavor = 0; - /// - /// if (this.radioZip64AsNecessary.Checked) - /// options.Zip64 = Zip64Option.AsNecessary; - /// else if (this.radioZip64Always.Checked) - /// options.Zip64 = Zip64Option.Always; - /// else options.Zip64 = Zip64Option.Never; - /// - /// options.Comment = String.Format("Encoding:{0} || Flavor:{1} || ZIP64:{2}\r\nCreated at {3} || {4}\r\n", - /// options.Encoding, - /// FlavorToString(options.ZipFlavor), - /// options.Zip64.ToString(), - /// System.DateTime.Now.ToString("yyyy-MMM-dd HH:mm:ss"), - /// this.Text); - /// - /// if (this.tbComment.Text != TB_COMMENT_NOTE) - /// options.Comment += this.tbComment.Text; - /// - /// _workerThread = new Thread(this.DoSave); - /// _workerThread.Name = "Zip Saver thread"; - /// _workerThread.Start(options); - /// this.Cursor = Cursors.WaitCursor; - /// } - /// - /// - /// private void DoSave(Object p) - /// { - /// WorkerOptions options = p as WorkerOptions; - /// try - /// { - /// using (var zip1 = new ZipFile()) - /// { - /// zip1.ProvisionalAlternateEncoding = System.Text.Encoding.GetEncoding(options.Encoding); - /// zip1.Comment = options.Comment; - /// zip1.AddDirectory(options.Folder); - /// _entriesToZip = zip1.EntryFileNames.Count; - /// SetProgressBars(); - /// zip1.SaveProgress += this.zip1_SaveProgress; - /// - /// zip1.UseZip64WhenSaving = options.Zip64; - /// - /// if (options.ZipFlavor == 1) - /// zip1.SaveSelfExtractor(options.ZipName, SelfExtractorFlavor.WinFormsApplication); - /// else if (options.ZipFlavor == 2) - /// zip1.SaveSelfExtractor(options.ZipName, SelfExtractorFlavor.ConsoleApplication); - /// else - /// zip1.Save(options.ZipName); - /// } - /// } - /// catch (System.Exception exc1) - /// { - /// MessageBox.Show(String.Format("Exception while zipping: {0}", exc1.Message)); - /// btnCancel_Click(null, null); - /// } - /// } - /// - /// - /// - /// void zip1_SaveProgress(object sender, SaveProgressEventArgs e) - /// { - /// switch (e.EventType) - /// { - /// case ZipProgressEventType.Saving_AfterWriteEntry: - /// StepArchiveProgress(e); - /// break; - /// case ZipProgressEventType.Saving_EntryBytesRead: - /// StepEntryProgress(e); - /// break; - /// case ZipProgressEventType.Saving_Completed: - /// SaveCompleted(); - /// break; - /// case ZipProgressEventType.Saving_AfterSaveTempArchive: - /// // this event only occurs when saving an SFX file - /// TempArchiveSaved(); - /// break; - /// } - /// if (_saveCanceled) - /// e.Cancel = true; - /// } - /// - /// - /// - /// private void StepArchiveProgress(SaveProgressEventArgs e) - /// { - /// if (this.progressBar1.InvokeRequired) - /// { - /// this.progressBar1.Invoke(new SaveEntryProgress(this.StepArchiveProgress), new object[] { e }); - /// } - /// else - /// { - /// if (!_saveCanceled) - /// { - /// _nFilesCompleted++; - /// this.progressBar1.PerformStep(); - /// _totalBytesAfterCompress += e.CurrentEntry.CompressedSize; - /// _totalBytesBeforeCompress += e.CurrentEntry.UncompressedSize; - /// - /// // reset the progress bar for the entry: - /// this.progressBar2.Value = this.progressBar2.Maximum = 1; - /// - /// this.Update(); - /// } - /// } - /// } - /// - /// - /// private void StepEntryProgress(SaveProgressEventArgs e) - /// { - /// if (this.progressBar2.InvokeRequired) - /// { - /// this.progressBar2.Invoke(new SaveEntryProgress(this.StepEntryProgress), new object[] { e }); - /// } - /// else - /// { - /// if (!_saveCanceled) - /// { - /// if (this.progressBar2.Maximum == 1) - /// { - /// // reset - /// Int64 max = e.TotalBytesToTransfer; - /// _progress2MaxFactor = 0; - /// while (max > System.Int32.MaxValue) - /// { - /// max /= 2; - /// _progress2MaxFactor++; - /// } - /// this.progressBar2.Maximum = (int)max; - /// lblStatus.Text = String.Format("{0} of {1} files...({2})", - /// _nFilesCompleted + 1, _entriesToZip, e.CurrentEntry.FileName); - /// } - /// - /// int xferred = e.BytesTransferred >> _progress2MaxFactor; - /// - /// this.progressBar2.Value = (xferred >= this.progressBar2.Maximum) - /// ? this.progressBar2.Maximum - /// : xferred; - /// - /// this.Update(); - /// } - /// } - /// } - /// - /// private void SaveCompleted() - /// { - /// if (this.lblStatus.InvokeRequired) - /// { - /// this.lblStatus.Invoke(new MethodInvoker(this.SaveCompleted)); - /// } - /// else - /// { - /// lblStatus.Text = String.Format("Done, Compressed {0} files, {1:N0}% of original.", - /// _nFilesCompleted, (100.00 * _totalBytesAfterCompress) / _totalBytesBeforeCompress); - /// ResetState(); - /// } - /// } - /// - /// private void ResetState() - /// { - /// this.btnCancel.Enabled = false; - /// this.btnOk.Enabled = true; - /// this.btnOk.Text = "Zip it!"; - /// this.progressBar1.Value = 0; - /// this.progressBar2.Value = 0; - /// this.Cursor = Cursors.Default; - /// if (!_workerThread.IsAlive) - /// _workerThread.Join(); - /// } - /// - /// - /// - /// - /// - /// - /// - public event EventHandler SaveProgress; - - - internal bool OnSaveBlock(ZipEntry entry, Int64 bytesXferred, Int64 totalBytesToXfer) - { - EventHandler sp = SaveProgress; - if (sp != null) - { - var e = SaveProgressEventArgs.ByteUpdate(ArchiveNameForEvent, entry, - bytesXferred, totalBytesToXfer); - sp(this, e); - if (e.Cancel) - _saveOperationCanceled = true; - } - return _saveOperationCanceled; - } - - private void OnSaveEntry(int current, ZipEntry entry, bool before) - { - EventHandler sp = SaveProgress; - if (sp != null) - { - var e = new SaveProgressEventArgs(ArchiveNameForEvent, before, _entries.Count, current, entry); - sp(this, e); - if (e.Cancel) - _saveOperationCanceled = true; - } - } - - private void OnSaveEvent(ZipProgressEventType eventFlavor) - { - EventHandler sp = SaveProgress; - if (sp != null) - { - var e = new SaveProgressEventArgs(ArchiveNameForEvent, eventFlavor); - sp(this, e); - if (e.Cancel) - _saveOperationCanceled = true; - } - } - - private void OnSaveStarted() - { - EventHandler sp = SaveProgress; - if (sp != null) - { - var e = SaveProgressEventArgs.Started(ArchiveNameForEvent); - sp(this, e); - if (e.Cancel) - _saveOperationCanceled = true; - } - } - private void OnSaveCompleted() - { - EventHandler sp = SaveProgress; - if (sp != null) - { - var e = SaveProgressEventArgs.Completed(ArchiveNameForEvent); - sp(this, e); - } - } - #endregion - - - #region Read - /// - /// An event handler invoked before, during, and after the reading of a zip archive. - /// - /// - /// - /// - /// Depending on the particular event being signaled, different properties on the - /// parameter are set. The following table - /// summarizes the available EventTypes and the conditions under which this - /// event handler is invoked with a ReadProgressEventArgs with the given EventType. - /// - /// - /// - /// - /// value of EntryType - /// Meaning and conditions - /// - /// - /// - /// ZipProgressEventType.Reading_Started - /// Fired just as ZipFile.Read() begins. Meaningful properties: ArchiveName. - /// - /// - /// - /// - /// ZipProgressEventType.Reading_Completed - /// Fired when ZipFile.Read() has completed. Meaningful properties: ArchiveName. - /// - /// - /// - /// - /// ZipProgressEventType.Reading_ArchiveBytesRead - /// Fired while reading, updates the number of bytes read for the entire archive. - /// Meaningful properties: ArchiveName, CurrentEntry, BytesTransferred, TotalBytesToTransfer. - /// - /// - /// - /// - /// ZipProgressEventType.Reading_BeforeReadEntry - /// Indicates an entry is about to be read from the archive. - /// Meaningful properties: ArchiveName, EntriesTotal. - /// - /// - /// - /// - /// ZipProgressEventType.Reading_AfterReadEntry - /// Indicates an entry has just been read from the archive. - /// Meaningful properties: ArchiveName, EntriesTotal, CurrentEntry. - /// - /// - /// - /// - /// - /// - /// - /// - /// - public event EventHandler ReadProgress; - - private void OnReadStarted() - { - EventHandler rp = ReadProgress; - if (rp != null) - { - var e = ReadProgressEventArgs.Started(ArchiveNameForEvent); - rp(this, e); - } - } - - private void OnReadCompleted() - { - EventHandler rp = ReadProgress; - if (rp != null) - { - var e = ReadProgressEventArgs.Completed(ArchiveNameForEvent); - rp(this, e); - } - } - - internal void OnReadBytes(ZipEntry entry) - { - EventHandler rp = ReadProgress; - if (rp != null) - { - var e = ReadProgressEventArgs.ByteUpdate(ArchiveNameForEvent, - entry, - ReadStream.Position, - LengthOfReadStream); - rp(this, e); - } - } - - internal void OnReadEntry(bool before, ZipEntry entry) - { - EventHandler rp = ReadProgress; - if (rp != null) - { - ReadProgressEventArgs e = (before) - ? ReadProgressEventArgs.Before(ArchiveNameForEvent, _entries.Count) - : ReadProgressEventArgs.After(ArchiveNameForEvent, entry, _entries.Count); - rp(this, e); - } - } - - private Int64 _lengthOfReadStream = -99; - private Int64 LengthOfReadStream - { - get - { - if (_lengthOfReadStream == -99) - { - _lengthOfReadStream = (_ReadStreamIsOurs) - ? SharedUtilities.GetFileLength(_name) - : -1L; - } - return _lengthOfReadStream; - } - } - #endregion - - - #region Extract - /// - /// An event handler invoked before, during, and after extraction of - /// entries in the zip archive. - /// - /// - /// - /// - /// Depending on the particular event, different properties on the parameter are set. The following - /// table summarizes the available EventTypes and the conditions under - /// which this event handler is invoked with a - /// ExtractProgressEventArgs with the given EventType. - /// - /// - /// - /// - /// value of EntryType - /// Meaning and conditions - /// - /// - /// - /// ZipProgressEventType.Extracting_BeforeExtractAll - /// - /// Set when ExtractAll() begins. The ArchiveName, Overwrite, and - /// ExtractLocation properties are meaningful. - /// - /// - /// - /// ZipProgressEventType.Extracting_AfterExtractAll - /// - /// Set when ExtractAll() has completed. The ArchiveName, Overwrite, - /// and ExtractLocation properties are meaningful. - /// - /// - /// - /// - /// ZipProgressEventType.Extracting_BeforeExtractEntry - /// - /// Set when an Extract() on an entry in the ZipFile has begun. - /// Properties that are meaningful: ArchiveName, EntriesTotal, - /// CurrentEntry, Overwrite, ExtractLocation, EntriesExtracted. - /// - /// - /// - /// - /// ZipProgressEventType.Extracting_AfterExtractEntry - /// - /// Set when an Extract() on an entry in the ZipFile has completed. - /// Properties that are meaningful: ArchiveName, EntriesTotal, - /// CurrentEntry, Overwrite, ExtractLocation, EntriesExtracted. - /// - /// - /// - /// - /// ZipProgressEventType.Extracting_EntryBytesWritten - /// - /// Set within a call to Extract() on an entry in the ZipFile, as data - /// is extracted for the entry. Properties that are meaningful: - /// ArchiveName, CurrentEntry, BytesTransferred, TotalBytesToTransfer. - /// - /// - /// - /// - /// ZipProgressEventType.Extracting_ExtractEntryWouldOverwrite - /// - /// Set within a call to Extract() on an entry in the ZipFile, when the - /// extraction would overwrite an existing file. This event type is used - /// only when ExtractExistingFileAction on the ZipFile or - /// ZipEntry is set to InvokeExtractProgressEvent. - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// private static bool justHadByteUpdate = false; - /// public static void ExtractProgress(object sender, ExtractProgressEventArgs e) - /// { - /// if(e.EventType == ZipProgressEventType.Extracting_EntryBytesWritten) - /// { - /// if (justHadByteUpdate) - /// Console.SetCursorPosition(0, Console.CursorTop); - /// - /// Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer, - /// e.BytesTransferred / (0.01 * e.TotalBytesToTransfer )); - /// justHadByteUpdate = true; - /// } - /// else if(e.EventType == ZipProgressEventType.Extracting_BeforeExtractEntry) - /// { - /// if (justHadByteUpdate) - /// Console.WriteLine(); - /// Console.WriteLine("Extracting: {0}", e.CurrentEntry.FileName); - /// justHadByteUpdate= false; - /// } - /// } - /// - /// public static ExtractZip(string zipToExtract, string directory) - /// { - /// string TargetDirectory= "extract"; - /// using (var zip = ZipFile.Read(zipToExtract)) { - /// zip.ExtractProgress += ExtractProgress; - /// foreach (var e in zip1) - /// { - /// e.Extract(TargetDirectory, true); - /// } - /// } - /// } - /// - /// - /// - /// Public Shared Sub Main(ByVal args As String()) - /// Dim ZipToUnpack As String = "C1P3SML.zip" - /// Dim TargetDir As String = "ExtractTest_Extract" - /// Console.WriteLine("Extracting file {0} to {1}", ZipToUnpack, TargetDir) - /// Using zip1 As ZipFile = ZipFile.Read(ZipToUnpack) - /// AddHandler zip1.ExtractProgress, AddressOf MyExtractProgress - /// Dim e As ZipEntry - /// For Each e In zip1 - /// e.Extract(TargetDir, True) - /// Next - /// End Using - /// End Sub - /// - /// Private Shared justHadByteUpdate As Boolean = False - /// - /// Public Shared Sub MyExtractProgress(ByVal sender As Object, ByVal e As ExtractProgressEventArgs) - /// If (e.EventType = ZipProgressEventType.Extracting_EntryBytesWritten) Then - /// If ExtractTest.justHadByteUpdate Then - /// Console.SetCursorPosition(0, Console.CursorTop) - /// End If - /// Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer, (CDbl(e.BytesTransferred) / (0.01 * e.TotalBytesToTransfer))) - /// ExtractTest.justHadByteUpdate = True - /// ElseIf (e.EventType = ZipProgressEventType.Extracting_BeforeExtractEntry) Then - /// If ExtractTest.justHadByteUpdate Then - /// Console.WriteLine - /// End If - /// Console.WriteLine("Extracting: {0}", e.CurrentEntry.FileName) - /// ExtractTest.justHadByteUpdate = False - /// End If - /// End Sub - /// - /// - /// - /// - /// - /// - public event EventHandler ExtractProgress; - - - - private void OnExtractEntry(int current, bool before, ZipEntry currentEntry, string path) - { - EventHandler ep = ExtractProgress; - if (ep != null) - { - var e = new ExtractProgressEventArgs(ArchiveNameForEvent, before, _entries.Count, current, currentEntry, path); - ep(this, e); - if (e.Cancel) - _extractOperationCanceled = true; - } - } - - - // Can be called from within ZipEntry._ExtractOne. - internal bool OnExtractBlock(ZipEntry entry, Int64 bytesWritten, Int64 totalBytesToWrite) - { - EventHandler ep = ExtractProgress; - if (ep != null) - { - var e = ExtractProgressEventArgs.ByteUpdate(ArchiveNameForEvent, entry, - bytesWritten, totalBytesToWrite); - ep(this, e); - if (e.Cancel) - _extractOperationCanceled = true; - } - return _extractOperationCanceled; - } - - - // Can be called from within ZipEntry.InternalExtract. - internal bool OnSingleEntryExtract(ZipEntry entry, string path, bool before) - { - EventHandler ep = ExtractProgress; - if (ep != null) - { - var e = (before) - ? ExtractProgressEventArgs.BeforeExtractEntry(ArchiveNameForEvent, entry, path) - : ExtractProgressEventArgs.AfterExtractEntry(ArchiveNameForEvent, entry, path); - ep(this, e); - if (e.Cancel) - _extractOperationCanceled = true; - } - return _extractOperationCanceled; - } - - internal bool OnExtractExisting(ZipEntry entry, string path) - { - EventHandler ep = ExtractProgress; - if (ep != null) - { - var e = ExtractProgressEventArgs.ExtractExisting(ArchiveNameForEvent, entry, path); - ep(this, e); - if (e.Cancel) - _extractOperationCanceled = true; - } - return _extractOperationCanceled; - } - - - private void OnExtractAllCompleted(string path) - { - EventHandler ep = ExtractProgress; - if (ep != null) - { - var e = ExtractProgressEventArgs.ExtractAllCompleted(ArchiveNameForEvent, - path ); - ep(this, e); - } - } - - - private void OnExtractAllStarted(string path) - { - EventHandler ep = ExtractProgress; - if (ep != null) - { - var e = ExtractProgressEventArgs.ExtractAllStarted(ArchiveNameForEvent, - path ); - ep(this, e); - } - } - - - #endregion - - - - #region Add - /// - /// An event handler invoked before, during, and after Adding entries to a zip archive. - /// - /// - /// - /// Adding a large number of entries to a zip file can take a long - /// time. For example, when calling on a - /// directory that contains 50,000 files, it could take 3 minutes or so. - /// This event handler allws an application to track the progress of the Add - /// operation, and to optionally cancel a lengthy Add operation. - /// - /// - /// - /// - /// - /// int _numEntriesToAdd= 0; - /// int _numEntriesAdded= 0; - /// void AddProgressHandler(object sender, AddProgressEventArgs e) - /// { - /// switch (e.EventType) - /// { - /// case ZipProgressEventType.Adding_Started: - /// Console.WriteLine("Adding files to the zip..."); - /// break; - /// case ZipProgressEventType.Adding_AfterAddEntry: - /// _numEntriesAdded++; - /// Console.WriteLine(String.Format("Adding file {0}/{1} :: {2}", - /// _numEntriesAdded, _numEntriesToAdd, e.CurrentEntry.FileName)); - /// break; - /// case ZipProgressEventType.Adding_Completed: - /// Console.WriteLine("Added all files"); - /// break; - /// } - /// } - /// - /// void CreateTheZip() - /// { - /// using (ZipFile zip = new ZipFile()) - /// { - /// zip.AddProgress += AddProgressHandler; - /// zip.AddDirectory(System.IO.Path.GetFileName(DirToZip)); - /// zip.Save(ZipFileToCreate); - /// } - /// } - /// - /// - /// - /// - /// - /// Private Sub AddProgressHandler(ByVal sender As Object, ByVal e As AddProgressEventArgs) - /// Select Case e.EventType - /// Case ZipProgressEventType.Adding_Started - /// Console.WriteLine("Adding files to the zip...") - /// Exit Select - /// Case ZipProgressEventType.Adding_AfterAddEntry - /// Console.WriteLine(String.Format("Adding file {0}", e.CurrentEntry.FileName)) - /// Exit Select - /// Case ZipProgressEventType.Adding_Completed - /// Console.WriteLine("Added all files") - /// Exit Select - /// End Select - /// End Sub - /// - /// Sub CreateTheZip() - /// Using zip as ZipFile = New ZipFile - /// AddHandler zip.AddProgress, AddressOf AddProgressHandler - /// zip.AddDirectory(System.IO.Path.GetFileName(DirToZip)) - /// zip.Save(ZipFileToCreate); - /// End Using - /// End Sub - /// - /// - /// - /// - /// - /// - /// - /// - public event EventHandler AddProgress; - - private void OnAddStarted() - { - EventHandler ap = AddProgress; - if (ap != null) - { - var e = AddProgressEventArgs.Started(ArchiveNameForEvent); - ap(this, e); - if (e.Cancel) // workitem 13371 - _addOperationCanceled = true; - } - } - - private void OnAddCompleted() - { - EventHandler ap = AddProgress; - if (ap != null) - { - var e = AddProgressEventArgs.Completed(ArchiveNameForEvent); - ap(this, e); - } - } - - internal void AfterAddEntry(ZipEntry entry) - { - EventHandler ap = AddProgress; - if (ap != null) - { - var e = AddProgressEventArgs.AfterEntry(ArchiveNameForEvent, entry, _entries.Count); - ap(this, e); - if (e.Cancel) // workitem 13371 - _addOperationCanceled = true; - } - } - - #endregion - - - - #region Error - /// - /// An event that is raised when an error occurs during open or read of files - /// while saving a zip archive. - /// - /// - /// - /// - /// Errors can occur as a file is being saved to the zip archive. For - /// example, the File.Open may fail, or a File.Read may fail, because of - /// lock conflicts or other reasons. If you add a handler to this event, - /// you can handle such errors in your own code. If you don't add a - /// handler, the library will throw an exception if it encounters an I/O - /// error during a call to Save(). - /// - /// - /// - /// Setting a handler implicitly sets to - /// ZipErrorAction.InvokeErrorEvent. - /// - /// - /// - /// The handler you add applies to all items that are - /// subsequently added to the ZipFile instance. If you set this - /// property after you have added items to the ZipFile, but before you - /// have called Save(), errors that occur while saving those items - /// will not cause the error handler to be invoked. - /// - /// - /// - /// If you want to handle any errors that occur with any entry in the zip - /// file using the same error handler, then add your error handler once, - /// before adding any entries to the zip archive. - /// - /// - /// - /// In the error handler method, you need to set the property on the - /// ZipErrorEventArgs.CurrentEntry. This communicates back to - /// DotNetZip what you would like to do with this particular error. Within - /// an error handler, if you set the ZipEntry.ZipErrorAction property - /// on the ZipEntry to ZipErrorAction.InvokeErrorEvent or if - /// you don't set it at all, the library will throw the exception. (It is the - /// same as if you had set the ZipEntry.ZipErrorAction property on the - /// ZipEntry to ZipErrorAction.Throw.) If you set the - /// ZipErrorEventArgs.Cancel to true, the entire Save() will be - /// canceled. - /// - /// - /// - /// In the case that you use ZipErrorAction.Skip, implying that - /// you want to skip the entry for which there's been an error, DotNetZip - /// tries to seek backwards in the output stream, and truncate all bytes - /// written on behalf of that particular entry. This works only if the - /// output stream is seekable. It will not work, for example, when using - /// ASPNET's Response.OutputStream. - /// - /// - /// - /// - /// - /// - /// This example shows how to use an event handler to handle - /// errors during save of the zip file. - /// - /// - /// public static void MyZipError(object sender, ZipErrorEventArgs e) - /// { - /// Console.WriteLine("Error saving {0}...", e.FileName); - /// Console.WriteLine(" Exception: {0}", e.exception); - /// ZipEntry entry = e.CurrentEntry; - /// string response = null; - /// // Ask the user whether he wants to skip this error or not - /// do - /// { - /// Console.Write("Retry, Skip, Throw, or Cancel ? (R/S/T/C) "); - /// response = Console.ReadLine(); - /// Console.WriteLine(); - /// - /// } while (response != null && - /// response[0]!='S' && response[0]!='s' && - /// response[0]!='R' && response[0]!='r' && - /// response[0]!='T' && response[0]!='t' && - /// response[0]!='C' && response[0]!='c'); - /// - /// e.Cancel = (response[0]=='C' || response[0]=='c'); - /// - /// if (response[0]=='S' || response[0]=='s') - /// entry.ZipErrorAction = ZipErrorAction.Skip; - /// else if (response[0]=='R' || response[0]=='r') - /// entry.ZipErrorAction = ZipErrorAction.Retry; - /// else if (response[0]=='T' || response[0]=='t') - /// entry.ZipErrorAction = ZipErrorAction.Throw; - /// } - /// - /// public void SaveTheFile() - /// { - /// string directoryToZip = "fodder"; - /// string directoryInArchive = "files"; - /// string zipFileToCreate = "Archive.zip"; - /// using (var zip = new ZipFile()) - /// { - /// // set the event handler before adding any entries - /// zip.ZipError += MyZipError; - /// zip.AddDirectory(directoryToZip, directoryInArchive); - /// zip.Save(zipFileToCreate); - /// } - /// } - /// - /// - /// - /// Private Sub MyZipError(ByVal sender As Object, ByVal e As Ionic.Zip.ZipErrorEventArgs) - /// ' At this point, the application could prompt the user for an action to take. - /// ' But in this case, this application will simply automatically skip the file, in case of error. - /// Console.WriteLine("Zip Error, entry {0}", e.CurrentEntry.FileName) - /// Console.WriteLine(" Exception: {0}", e.exception) - /// ' set the desired ZipErrorAction on the CurrentEntry to communicate that to DotNetZip - /// e.CurrentEntry.ZipErrorAction = Zip.ZipErrorAction.Skip - /// End Sub - /// - /// Public Sub SaveTheFile() - /// Dim directoryToZip As String = "fodder" - /// Dim directoryInArchive As String = "files" - /// Dim zipFileToCreate as String = "Archive.zip" - /// Using zipArchive As ZipFile = New ZipFile - /// ' set the event handler before adding any entries - /// AddHandler zipArchive.ZipError, AddressOf MyZipError - /// zipArchive.AddDirectory(directoryToZip, directoryInArchive) - /// zipArchive.Save(zipFileToCreate) - /// End Using - /// End Sub - /// - /// - /// - /// - /// - public event EventHandler ZipError; - - internal bool OnZipErrorSaving(ZipEntry entry, Exception exc) - { - if (ZipError != null) - { - lock (LOCK) - { - var e = ZipErrorEventArgs.Saving(this.Name, entry, exc); - ZipError(this, e); - if (e.Cancel) - _saveOperationCanceled = true; - } - } - return _saveOperationCanceled; - } - #endregion - - } -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Extract.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Extract.cs deleted file mode 100644 index 531c0f3a..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Extract.cs +++ /dev/null @@ -1,298 +0,0 @@ -// ZipFile.Extract.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2009 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:45:18> -// -// ------------------------------------------------------------------ -// -// This module defines the methods for Extract operations on zip files. -// -// ------------------------------------------------------------------ -// - - -using System; -using System.IO; -using System.Collections.Generic; - -namespace Ionic.Zip -{ - - public partial class ZipFile - { - - /// - /// Extracts all of the items in the zip archive, to the specified path in the - /// filesystem. The path can be relative or fully-qualified. - /// - /// - /// - /// - /// This method will extract all entries in the ZipFile to the - /// specified path. - /// - /// - /// - /// If an extraction of a file from the zip archive would overwrite an - /// existing file in the filesystem, the action taken is dictated by the - /// ExtractExistingFile property, which overrides any setting you may have - /// made on individual ZipEntry instances. By default, if you have not - /// set that property on the ZipFile instance, the entry will not - /// be extracted, the existing file will not be overwritten and an - /// exception will be thrown. To change this, set the property, or use the - /// overload that allows you to - /// specify an ExtractExistingFileAction parameter. - /// - /// - /// - /// The action to take when an extract would overwrite an existing file - /// applies to all entries. If you want to set this on a per-entry basis, - /// then you must use one of the ZipEntry.Extract methods. - /// - /// - /// - /// This method will send verbose output messages to the , if it is set on the ZipFile - /// instance. - /// - /// - /// - /// You may wish to take advantage of the ExtractProgress event. - /// - /// - /// - /// About timestamps: When extracting a file entry from a zip archive, the - /// extracted file gets the last modified time of the entry as stored in - /// the archive. The archive may also store extended file timestamp - /// information, including last accessed and created times. If these are - /// present in the ZipEntry, then the extracted file will also get - /// these times. - /// - /// - /// - /// A Directory entry is somewhat different. It will get the times as - /// described for a file entry, but, if there are file entries in the zip - /// archive that, when extracted, appear in the just-created directory, - /// then when those file entries are extracted, the last modified and last - /// accessed times of the directory will change, as a side effect. The - /// result is that after an extraction of a directory and a number of - /// files within the directory, the last modified and last accessed - /// timestamps on the directory will reflect the time that the last file - /// was extracted into the directory, rather than the time stored in the - /// zip archive for the directory. - /// - /// - /// - /// To compensate, when extracting an archive with ExtractAll, - /// DotNetZip will extract all the file and directory entries as described - /// above, but it will then make a second pass on the directories, and - /// reset the times on the directories to reflect what is stored in the - /// zip archive. - /// - /// - /// - /// This compensation is performed only within the context of an - /// ExtractAll. If you call ZipEntry.Extract on a directory - /// entry, the timestamps on directory in the filesystem will reflect the - /// times stored in the zip. If you then call ZipEntry.Extract on - /// a file entry, which is extracted into the directory, the timestamps on - /// the directory will be updated to the current time. - /// - /// - /// - /// - /// This example extracts all the entries in a zip archive file, to the - /// specified target directory. The extraction will overwrite any - /// existing files silently. - /// - /// - /// String TargetDirectory= "unpack"; - /// using(ZipFile zip= ZipFile.Read(ZipFileToExtract)) - /// { - /// zip.ExtractExistingFile= ExtractExistingFileAction.OverwriteSilently; - /// zip.ExtractAll(TargetDirectory); - /// } - /// - /// - /// - /// Dim TargetDirectory As String = "unpack" - /// Using zip As ZipFile = ZipFile.Read(ZipFileToExtract) - /// zip.ExtractExistingFile= ExtractExistingFileAction.OverwriteSilently - /// zip.ExtractAll(TargetDirectory) - /// End Using - /// - /// - /// - /// - /// - /// - /// - /// The path to which the contents of the zipfile will be extracted. - /// The path can be relative or fully-qualified. - /// - /// - public void ExtractAll(string path) - { - _InternalExtractAll(path, true); - } - - - - /// - /// Extracts all of the items in the zip archive, to the specified path in the - /// filesystem, using the specified behavior when extraction would overwrite an - /// existing file. - /// - /// - /// - /// - /// - /// This method will extract all entries in the ZipFile to the specified - /// path. For an extraction that would overwrite an existing file, the behavior - /// is dictated by , which overrides any - /// setting you may have made on individual ZipEntry instances. - /// - /// - /// - /// The action to take when an extract would overwrite an existing file - /// applies to all entries. If you want to set this on a per-entry basis, - /// then you must use or one of the similar methods. - /// - /// - /// - /// Calling this method is equivalent to setting the property and then calling . - /// - /// - /// - /// This method will send verbose output messages to the - /// , if it is set on the ZipFile instance. - /// - /// - /// - /// - /// This example extracts all the entries in a zip archive file, to the - /// specified target directory. It does not overwrite any existing files. - /// - /// String TargetDirectory= "c:\\unpack"; - /// using(ZipFile zip= ZipFile.Read(ZipFileToExtract)) - /// { - /// zip.ExtractAll(TargetDirectory, ExtractExistingFileAction.DontOverwrite); - /// } - /// - /// - /// - /// Dim TargetDirectory As String = "c:\unpack" - /// Using zip As ZipFile = ZipFile.Read(ZipFileToExtract) - /// zip.ExtractAll(TargetDirectory, ExtractExistingFileAction.DontOverwrite) - /// End Using - /// - /// - /// - /// - /// The path to which the contents of the zipfile will be extracted. - /// The path can be relative or fully-qualified. - /// - /// - /// - /// The action to take if extraction would overwrite an existing file. - /// - /// - public void ExtractAll(string path, ExtractExistingFileAction extractExistingFile) - { - ExtractExistingFile = extractExistingFile; - _InternalExtractAll(path, true); - } - - - private void _InternalExtractAll(string path, bool overrideExtractExistingProperty) - { - bool header = Verbose; - _inExtractAll = true; - try - { - OnExtractAllStarted(path); - - int n = 0; - foreach (ZipEntry e in _entries.Values) - { - if (header) - { - StatusMessageTextWriter.WriteLine("\n{1,-22} {2,-8} {3,4} {4,-8} {0}", - "Name", "Modified", "Size", "Ratio", "Packed"); - StatusMessageTextWriter.WriteLine(new System.String('-', 72)); - header = false; - } - if (Verbose) - { - StatusMessageTextWriter.WriteLine("{1,-22} {2,-8} {3,4:F0}% {4,-8} {0}", - e.FileName, - e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"), - e.UncompressedSize, - e.CompressionRatio, - e.CompressedSize); - if (!String.IsNullOrEmpty(e.Comment)) - StatusMessageTextWriter.WriteLine(" Comment: {0}", e.Comment); - } - e.Password = _Password; // this may be null - OnExtractEntry(n, true, e, path); - if (overrideExtractExistingProperty) - e.ExtractExistingFile = this.ExtractExistingFile; - e.Extract(path); - n++; - OnExtractEntry(n, false, e, path); - if (_extractOperationCanceled) - break; - } - - if (!_extractOperationCanceled) - { - // workitem 8264: - // now, set times on directory entries, again. - // The problem is, extracting a file changes the times on the parent - // directory. So after all files have been extracted, we have to - // run through the directories again. - foreach (ZipEntry e in _entries.Values) - { - // check if it is a directory - if ((e.IsDirectory) || (e.FileName.EndsWith("/"))) - { - string outputFile = (e.FileName.StartsWith("/")) - ? Path.Combine(path, e.FileName.Substring(1)) - : Path.Combine(path, e.FileName); - - e._SetTimes(outputFile, false); - } - } - OnExtractAllCompleted(path); - } - - } - finally - { - - _inExtractAll = false; - } - } - - - } -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Read.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Read.cs deleted file mode 100644 index 2dac1e5d..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Read.cs +++ /dev/null @@ -1,1110 +0,0 @@ -// ZipFile.Read.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-August-05 11:38:59> -// -// ------------------------------------------------------------------ -// -// This module defines the methods for Reading zip files. -// -// ------------------------------------------------------------------ -// - - -using System; -using System.IO; -using System.Collections.Generic; - -namespace Ionic.Zip -{ - /// - /// A class for collecting the various options that can be used when - /// Reading zip files for extraction or update. - /// - /// - /// - /// - /// When reading a zip file, there are several options an - /// application can set, to modify how the file is read, or what - /// the library does while reading. This class collects those - /// options into one container. - /// - /// - /// - /// Pass an instance of the ReadOptions class into the - /// ZipFile.Read() method. - /// - /// - /// . - /// . - /// - public class ReadOptions - { - /// - /// An event handler for Read operations. When opening large zip - /// archives, you may want to display a progress bar or other - /// indicator of status progress while reading. This parameter - /// allows you to specify a ReadProgress Event Handler directly. - /// When you call Read(), the progress event is invoked as - /// necessary. - /// - public EventHandler ReadProgress { get; set; } - - /// - /// The System.IO.TextWriter to use for writing verbose status messages - /// during operations on the zip archive. A console application may wish to - /// pass System.Console.Out to get messages on the Console. A graphical - /// or headless application may wish to capture the messages in a different - /// TextWriter, such as a System.IO.StringWriter. - /// - public TextWriter StatusMessageWriter { get; set; } - - /// - /// The System.Text.Encoding to use when reading in the zip archive. Be - /// careful specifying the encoding. If the value you use here is not the same - /// as the Encoding used when the zip archive was created (possibly by a - /// different archiver) you will get unexpected results and possibly exceptions. - /// - /// - /// - /// - public System.Text.Encoding @Encoding { get; set; } - } - - - public partial class ZipFile - { - /// - /// Reads a zip file archive and returns the instance. - /// - /// - /// - /// - /// The stream is read using the default System.Text.Encoding, which is the - /// IBM437 codepage. - /// - /// - /// - /// - /// Thrown if the ZipFile cannot be read. The implementation of this method - /// relies on System.IO.File.OpenRead, which can throw a variety of exceptions, - /// including specific exceptions if a file is not found, an unauthorized access - /// exception, exceptions for poorly formatted filenames, and so on. - /// - /// - /// - /// The name of the zip archive to open. This can be a fully-qualified or relative - /// pathname. - /// - /// - /// . - /// - /// The instance read from the zip archive. - /// - public static ZipFile Read(string fileName) - { - return ZipFile.Read(fileName, null, null, null); - } - - - /// - /// Reads a zip file archive from the named filesystem file using the - /// specified options. - /// - /// - /// - /// - /// This version of the Read() method allows the caller to pass - /// in a TextWriter an Encoding, via an instance of the - /// ReadOptions class. The ZipFile is read in using the - /// specified encoding for entries where UTF-8 encoding is not - /// explicitly specified. - /// - /// - /// - /// - /// - /// - /// This example shows how to read a zip file using the Big-5 Chinese - /// code page (950), and extract each entry in the zip file, while - /// sending status messages out to the Console. - /// - /// - /// - /// For this code to work as intended, the zipfile must have been - /// created using the big5 code page (CP950). This is typical, for - /// example, when using WinRar on a machine with CP950 set as the - /// default code page. In that case, the names of entries within the - /// Zip archive will be stored in that code page, and reading the zip - /// archive must be done using that code page. If the application did - /// not use the correct code page in ZipFile.Read(), then names of - /// entries within the zip archive would not be correctly retrieved. - /// - /// - /// - /// string zipToExtract = "MyArchive.zip"; - /// string extractDirectory = "extract"; - /// var options = new ReadOptions - /// { - /// StatusMessageWriter = System.Console.Out, - /// Encoding = System.Text.Encoding.GetEncoding(950) - /// }; - /// using (ZipFile zip = ZipFile.Read(zipToExtract, options)) - /// { - /// foreach (ZipEntry e in zip) - /// { - /// e.Extract(extractDirectory); - /// } - /// } - /// - /// - /// - /// - /// Dim zipToExtract as String = "MyArchive.zip" - /// Dim extractDirectory as String = "extract" - /// Dim options as New ReadOptions - /// options.Encoding = System.Text.Encoding.GetEncoding(950) - /// options.StatusMessageWriter = System.Console.Out - /// Using zip As ZipFile = ZipFile.Read(zipToExtract, options) - /// Dim e As ZipEntry - /// For Each e In zip - /// e.Extract(extractDirectory) - /// Next - /// End Using - /// - /// - /// - /// - /// - /// - /// - /// This example shows how to read a zip file using the default - /// code page, to remove entries that have a modified date before a given threshold, - /// sending status messages out to a StringWriter. - /// - /// - /// - /// var options = new ReadOptions - /// { - /// StatusMessageWriter = new System.IO.StringWriter() - /// }; - /// using (ZipFile zip = ZipFile.Read("PackedDocuments.zip", options)) - /// { - /// var Threshold = new DateTime(2007,7,4); - /// // We cannot remove the entry from the list, within the context of - /// // an enumeration of said list. - /// // So we add the doomed entry to a list to be removed later. - /// // pass 1: mark the entries for removal - /// var MarkedEntries = new System.Collections.Generic.List<ZipEntry>(); - /// foreach (ZipEntry e in zip) - /// { - /// if (e.LastModified < Threshold) - /// MarkedEntries.Add(e); - /// } - /// // pass 2: actually remove the entry. - /// foreach (ZipEntry zombie in MarkedEntries) - /// zip.RemoveEntry(zombie); - /// zip.Comment = "This archive has been updated."; - /// zip.Save(); - /// } - /// // can now use contents of sw, eg store in an audit log - /// - /// - /// - /// Dim options as New ReadOptions - /// options.StatusMessageWriter = New System.IO.StringWriter - /// Using zip As ZipFile = ZipFile.Read("PackedDocuments.zip", options) - /// Dim Threshold As New DateTime(2007, 7, 4) - /// ' We cannot remove the entry from the list, within the context of - /// ' an enumeration of said list. - /// ' So we add the doomed entry to a list to be removed later. - /// ' pass 1: mark the entries for removal - /// Dim MarkedEntries As New System.Collections.Generic.List(Of ZipEntry) - /// Dim e As ZipEntry - /// For Each e In zip - /// If (e.LastModified < Threshold) Then - /// MarkedEntries.Add(e) - /// End If - /// Next - /// ' pass 2: actually remove the entry. - /// Dim zombie As ZipEntry - /// For Each zombie In MarkedEntries - /// zip.RemoveEntry(zombie) - /// Next - /// zip.Comment = "This archive has been updated." - /// zip.Save - /// End Using - /// ' can now use contents of sw, eg store in an audit log - /// - /// - /// - /// - /// Thrown if the zipfile cannot be read. The implementation of - /// this method relies on System.IO.File.OpenRead, which - /// can throw a variety of exceptions, including specific - /// exceptions if a file is not found, an unauthorized access - /// exception, exceptions for poorly formatted filenames, and so - /// on. - /// - /// - /// - /// The name of the zip archive to open. - /// This can be a fully-qualified or relative pathname. - /// - /// - /// - /// The set of options to use when reading the zip file. - /// - /// - /// The ZipFile instance read from the zip archive. - /// - /// - /// - public static ZipFile Read(string fileName, - ReadOptions options) - { - if (options == null) - throw new ArgumentNullException("options"); - return Read(fileName, - options.StatusMessageWriter, - options.Encoding, - options.ReadProgress); - } - - /// - /// Reads a zip file archive using the specified text encoding, the specified - /// TextWriter for status messages, and the specified ReadProgress event handler, - /// and returns the instance. - /// - /// - /// - /// The name of the zip archive to open. - /// This can be a fully-qualified or relative pathname. - /// - /// - /// - /// An event handler for Read operations. - /// - /// - /// - /// The System.IO.TextWriter to use for writing verbose status messages - /// during operations on the zip archive. A console application may wish to - /// pass System.Console.Out to get messages on the Console. A graphical - /// or headless application may wish to capture the messages in a different - /// TextWriter, such as a System.IO.StringWriter. - /// - /// - /// - /// The System.Text.Encoding to use when reading in the zip archive. Be - /// careful specifying the encoding. If the value you use here is not the same - /// as the Encoding used when the zip archive was created (possibly by a - /// different archiver) you will get unexpected results and possibly exceptions. - /// - /// - /// The instance read from the zip archive. - /// - private static ZipFile Read(string fileName, - TextWriter statusMessageWriter, - System.Text.Encoding encoding, - EventHandler readProgress) - { - ZipFile zf = new ZipFile(); - zf.AlternateEncoding = encoding ?? DefaultEncoding; - zf.AlternateEncodingUsage = ZipOption.Always; - zf._StatusMessageTextWriter = statusMessageWriter; - zf._name = fileName; - if (readProgress != null) - zf.ReadProgress = readProgress; - - if (zf.Verbose) zf._StatusMessageTextWriter.WriteLine("reading from {0}...", fileName); - - ReadIntoInstance(zf); - zf._fileAlreadyExists = true; - - return zf; - } - - /// - /// Reads a zip archive from a stream. - /// - /// - /// - /// - /// - /// When reading from a file, it's probably easier to just use - /// ZipFile.Read(String, ReadOptions). This - /// overload is useful when when the zip archive content is - /// available from an already-open stream. The stream must be - /// open and readable and seekable when calling this method. The - /// stream is left open when the reading is completed. - /// - /// - /// - /// Using this overload, the stream is read using the default - /// System.Text.Encoding, which is the IBM437 - /// codepage. If you want to specify the encoding to use when - /// reading the zipfile content, see - /// ZipFile.Read(Stream, ReadOptions). This - /// - /// - /// - /// Reading of zip content begins at the current position in the - /// stream. This means if you have a stream that concatenates - /// regular data and zip data, if you position the open, readable - /// stream at the start of the zip data, you will be able to read - /// the zip archive using this constructor, or any of the ZipFile - /// constructors that accept a as - /// input. Some examples of where this might be useful: the zip - /// content is concatenated at the end of a regular EXE file, as - /// some self-extracting archives do. (Note: SFX files produced - /// by DotNetZip do not work this way; they can be read as normal - /// ZIP files). Another example might be a stream being read from - /// a database, where the zip content is embedded within an - /// aggregate stream of data. - /// - /// - /// - /// - /// - /// - /// This example shows how to Read zip content from a stream, and - /// extract one entry into a different stream. In this example, - /// the filename "NameOfEntryInArchive.doc", refers only to the - /// name of the entry within the zip archive. A file by that - /// name is not created in the filesystem. The I/O is done - /// strictly with the given streams. - /// - /// - /// - /// using (ZipFile zip = ZipFile.Read(InputStream)) - /// { - /// zip.Extract("NameOfEntryInArchive.doc", OutputStream); - /// } - /// - /// - /// - /// Using zip as ZipFile = ZipFile.Read(InputStream) - /// zip.Extract("NameOfEntryInArchive.doc", OutputStream) - /// End Using - /// - /// - /// - /// the stream containing the zip data. - /// - /// The ZipFile instance read from the stream - /// - public static ZipFile Read(Stream zipStream) - { - return Read(zipStream, null, null, null); - } - - /// - /// Reads a zip file archive from the given stream using the - /// specified options. - /// - /// - /// - /// - /// - /// When reading from a file, it's probably easier to just use - /// ZipFile.Read(String, ReadOptions). This - /// overload is useful when when the zip archive content is - /// available from an already-open stream. The stream must be - /// open and readable and seekable when calling this method. The - /// stream is left open when the reading is completed. - /// - /// - /// - /// Reading of zip content begins at the current position in the - /// stream. This means if you have a stream that concatenates - /// regular data and zip data, if you position the open, readable - /// stream at the start of the zip data, you will be able to read - /// the zip archive using this constructor, or any of the ZipFile - /// constructors that accept a as - /// input. Some examples of where this might be useful: the zip - /// content is concatenated at the end of a regular EXE file, as - /// some self-extracting archives do. (Note: SFX files produced - /// by DotNetZip do not work this way; they can be read as normal - /// ZIP files). Another example might be a stream being read from - /// a database, where the zip content is embedded within an - /// aggregate stream of data. - /// - /// - /// - /// the stream containing the zip data. - /// - /// - /// The set of options to use when reading the zip file. - /// - /// - /// - /// Thrown if the zip archive cannot be read. - /// - /// - /// The ZipFile instance read from the stream. - /// - /// - /// - public static ZipFile Read(Stream zipStream, ReadOptions options) - { - if (options == null) - throw new ArgumentNullException("options"); - - return Read(zipStream, - options.StatusMessageWriter, - options.Encoding, - options.ReadProgress); - } - - - - /// - /// Reads a zip archive from a stream, using the specified text Encoding, the - /// specified TextWriter for status messages, - /// and the specified ReadProgress event handler. - /// - /// - /// - /// - /// Reading of zip content begins at the current position in the stream. This - /// means if you have a stream that concatenates regular data and zip data, if - /// you position the open, readable stream at the start of the zip data, you - /// will be able to read the zip archive using this constructor, or any of the - /// ZipFile constructors that accept a as - /// input. Some examples of where this might be useful: the zip content is - /// concatenated at the end of a regular EXE file, as some self-extracting - /// archives do. (Note: SFX files produced by DotNetZip do not work this - /// way). Another example might be a stream being read from a database, where - /// the zip content is embedded within an aggregate stream of data. - /// - /// - /// - /// the stream containing the zip data. - /// - /// - /// The System.IO.TextWriter to which verbose status messages are written - /// during operations on the ZipFile. For example, in a console - /// application, System.Console.Out works, and will get a message for each entry - /// added to the ZipFile. If the TextWriter is null, no verbose messages - /// are written. - /// - /// - /// - /// The text encoding to use when reading entries that do not have the UTF-8 - /// encoding bit set. Be careful specifying the encoding. If the value you use - /// here is not the same as the Encoding used when the zip archive was created - /// (possibly by a different archiver) you will get unexpected results and - /// possibly exceptions. See the - /// property for more information. - /// - /// - /// - /// An event handler for Read operations. - /// - /// - /// an instance of ZipFile - private static ZipFile Read(Stream zipStream, - TextWriter statusMessageWriter, - System.Text.Encoding encoding, - EventHandler readProgress) - { - if (zipStream == null) - throw new ArgumentNullException("zipStream"); - - ZipFile zf = new ZipFile(); - zf._StatusMessageTextWriter = statusMessageWriter; - zf._alternateEncoding = encoding ?? ZipFile.DefaultEncoding; - zf._alternateEncodingUsage = ZipOption.Always; - if (readProgress != null) - zf.ReadProgress += readProgress; - zf._readstream = (zipStream.Position == 0L) - ? zipStream - : new OffsetStream(zipStream); - zf._ReadStreamIsOurs = false; - if (zf.Verbose) zf._StatusMessageTextWriter.WriteLine("reading from stream..."); - - ReadIntoInstance(zf); - return zf; - } - - - - private static void ReadIntoInstance(ZipFile zf) - { - Stream s = zf.ReadStream; - try - { - zf._readName = zf._name; // workitem 13915 - if (!s.CanSeek) - { - ReadIntoInstance_Orig(zf); - return; - } - - zf.OnReadStarted(); - - // 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 - { - zf._OffsetOfCentralDirectory = offset32; - // 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) - { - if (zf._ReadStreamIsOurs && zf._readstream != null) - { - try - { -#if NETCF - zf._readstream.Close(); -#else - zf._readstream.Dispose(); -#endif - zf._readstream = null; - } - finally { } - } - - throw new ZipException("Cannot read that as a ZipFile", ex1); - } - - // the instance has been read in - zf._contentsChanged = false; - } - - - - private static void Zip64SeekToCentralDirectory(ZipFile zf) - { - Stream s = zf.ReadStream; - byte[] block = new byte[16]; - - // seek back to find the ZIP64 EoCD. - // I think this might not work for .NET CF ? - s.Seek(-40, SeekOrigin.Current); - s.Read(block, 0, 16); - - Int64 offset64 = BitConverter.ToInt64(block, 8); - zf._OffsetOfCentralDirectory = 0xFFFFFFFF; - zf._OffsetOfCentralDirectory64 = offset64; - // change for workitem 8098 - s.Seek(offset64, SeekOrigin.Begin); - //zf.SeekFromOrigin(Offset64); - - uint datum = (uint)Ionic.Zip.SharedUtilities.ReadInt(s); - if (datum != ZipConstants.Zip64EndOfCentralDirectoryRecordSignature) - throw new BadReadException(String.Format(" Bad signature (0x{0:X8}) looking for ZIP64 EoCD Record at position 0x{1:X8}", datum, s.Position)); - - s.Read(block, 0, 8); - Int64 Size = BitConverter.ToInt64(block, 0); - - block = new byte[Size]; - s.Read(block, 0, block.Length); - - offset64 = BitConverter.ToInt64(block, 36); - // change for workitem 8098 - s.Seek(offset64, SeekOrigin.Begin); - //zf.SeekFromOrigin(Offset64); - } - - - private static uint ReadFirstFourBytes(Stream s) - { - uint datum = (uint)Ionic.Zip.SharedUtilities.ReadInt(s); - return datum; - } - - - - private static void ReadCentralDirectory(ZipFile zf) - { - // We must have the central directory footer record, in order to properly - // read zip dir entries from the central directory. This because the logic - // knows when to open a spanned file when the volume number for the central - // directory differs from the volume number for the zip entry. The - // _diskNumberWithCd was set when originally finding the offset for the - // start of the Central Directory. - - // workitem 9214 - bool inputUsesZip64 = false; - ZipEntry de; - // in lieu of hashset, use a dictionary - var previouslySeen = new Dictionary(); - while ((de = ZipEntry.ReadDirEntry(zf, previouslySeen)) != null) - { - de.ResetDirEntry(); - zf.OnReadEntry(true, null); - - if (zf.Verbose) - zf.StatusMessageTextWriter.WriteLine("entry {0}", de.FileName); - - zf._entries.Add(de.FileName,de); - - // workitem 9214 - if (de._InputUsesZip64) inputUsesZip64 = true; - previouslySeen.Add(de.FileName, null); // to prevent dupes - } - - // workitem 9214; auto-set the zip64 flag - if (inputUsesZip64) zf.UseZip64WhenSaving = Zip64Option.Always; - - // workitem 8299 - if (zf._locEndOfCDS > 0) - zf.ReadStream.Seek(zf._locEndOfCDS, SeekOrigin.Begin); - - ReadCentralDirectoryFooter(zf); - - if (zf.Verbose && !String.IsNullOrEmpty(zf.Comment)) - zf.StatusMessageTextWriter.WriteLine("Zip file Comment: {0}", zf.Comment); - - // We keep the read stream open after reading. - - if (zf.Verbose) - zf.StatusMessageTextWriter.WriteLine("read in {0} entries.", zf._entries.Count); - - zf.OnReadCompleted(); - } - - - - - // build the TOC by reading each entry in the file. - private static void ReadIntoInstance_Orig(ZipFile zf) - { - zf.OnReadStarted(); - //zf._entries = new System.Collections.Generic.List(); - zf._entries = new System.Collections.Generic.Dictionary(); - - ZipEntry e; - if (zf.Verbose) - if (zf.Name == null) - zf.StatusMessageTextWriter.WriteLine("Reading zip from stream..."); - else - zf.StatusMessageTextWriter.WriteLine("Reading zip {0}...", zf.Name); - - // work item 6647: PK00 (packed to removable disk) - bool firstEntry = true; - ZipContainer zc = new ZipContainer(zf); - while ((e = ZipEntry.ReadEntry(zc, firstEntry)) != null) - { - if (zf.Verbose) - zf.StatusMessageTextWriter.WriteLine(" {0}", e.FileName); - - zf._entries.Add(e.FileName,e); - firstEntry = false; - } - - // read the zipfile's central directory structure here. - // workitem 9912 - // But, because it may be corrupted, ignore errors. - try - { - ZipEntry de; - // in lieu of hashset, use a dictionary - var previouslySeen = new Dictionary(); - while ((de = ZipEntry.ReadDirEntry(zf, previouslySeen)) != null) - { - // Housekeeping: Since ZipFile exposes ZipEntry elements in the enumerator, - // we need to copy the comment that we grab from the ZipDirEntry - // into the ZipEntry, so the application can access the comment. - // Also since ZipEntry is used to Write zip files, we need to copy the - // file attributes to the ZipEntry as appropriate. - ZipEntry e1 = zf._entries[de.FileName]; - if (e1 != null) - { - e1._Comment = de.Comment; - if (de.IsDirectory) e1.MarkAsDirectory(); - } - previouslySeen.Add(de.FileName,null); // to prevent dupes - } - - // workitem 8299 - if (zf._locEndOfCDS > 0) - zf.ReadStream.Seek(zf._locEndOfCDS, SeekOrigin.Begin); - - ReadCentralDirectoryFooter(zf); - - if (zf.Verbose && !String.IsNullOrEmpty(zf.Comment)) - zf.StatusMessageTextWriter.WriteLine("Zip file Comment: {0}", zf.Comment); - } - catch (ZipException) { } - catch (IOException) { } - - zf.OnReadCompleted(); - } - - - - - private static void ReadCentralDirectoryFooter(ZipFile zf) - { - Stream s = zf.ReadStream; - int signature = Ionic.Zip.SharedUtilities.ReadSignature(s); - - byte[] block = null; - int j = 0; - if (signature == ZipConstants.Zip64EndOfCentralDirectoryRecordSignature) - { - // We have a ZIP64 EOCD - // This data block is 4 bytes sig, 8 bytes size, 44 bytes fixed data, - // followed by a variable-sized extension block. We have read the sig already. - // 8 - datasize (64 bits) - // 2 - version made by - // 2 - version needed to extract - // 4 - number of this disk - // 4 - number of the disk with the start of the CD - // 8 - total number of entries in the CD on this disk - // 8 - total number of entries in the CD - // 8 - size of the CD - // 8 - offset of the CD - // ----------------------- - // 52 bytes - - block = new byte[8 + 44]; - s.Read(block, 0, block.Length); - - Int64 DataSize = BitConverter.ToInt64(block, 0); // == 44 + the variable length - - if (DataSize < 44) - throw new ZipException("Bad size in the ZIP64 Central Directory."); - - zf._versionMadeBy = BitConverter.ToUInt16(block, j); - j += 2; - zf._versionNeededToExtract = BitConverter.ToUInt16(block, j); - j += 2; - zf._diskNumberWithCd = BitConverter.ToUInt32(block, j); - j += 2; - - //zf._diskNumberWithCd++; // hack!! - - // read the extended block - block = new byte[DataSize - 44]; - s.Read(block, 0, block.Length); - // discard the result - - signature = Ionic.Zip.SharedUtilities.ReadSignature(s); - if (signature != ZipConstants.Zip64EndOfCentralDirectoryLocatorSignature) - throw new ZipException("Inconsistent metadata in the ZIP64 Central Directory."); - - block = new byte[16]; - s.Read(block, 0, block.Length); - // discard the result - - signature = Ionic.Zip.SharedUtilities.ReadSignature(s); - } - - // Throw if this is not a signature for "end of central directory record" - // This is a sanity check. - if (signature != ZipConstants.EndOfCentralDirectorySignature) - { - s.Seek(-4, SeekOrigin.Current); - throw new BadReadException(String.Format("Bad signature ({0:X8}) at position 0x{1:X8}", - signature, s.Position)); - } - - // read the End-of-Central-Directory-Record - block = new byte[16]; - zf.ReadStream.Read(block, 0, block.Length); - - // off sz data - // ------------------------------------------------------- - // 0 4 end of central dir signature (0x06054b50) - // 4 2 number of this disk - // 6 2 number of the disk with start of the central directory - // 8 2 total number of entries in the central directory on this disk - // 10 2 total number of entries in the central directory - // 12 4 size of the central directory - // 16 4 offset of start of central directory with respect to the starting disk number - // 20 2 ZIP file comment length - // 22 ?? ZIP file comment - - if (zf._diskNumberWithCd == 0) - { - zf._diskNumberWithCd = BitConverter.ToUInt16(block, 2); - //zf._diskNumberWithCd++; // hack!! - } - - // read the comment here - ReadZipFileComment(zf); - } - - - - private static void ReadZipFileComment(ZipFile zf) - { - // read the comment here - byte[] block = new byte[2]; - zf.ReadStream.Read(block, 0, block.Length); - - Int16 commentLength = (short)(block[0] + block[1] * 256); - if (commentLength > 0) - { - block = new byte[commentLength]; - zf.ReadStream.Read(block, 0, block.Length); - - // workitem 10392 - prefer ProvisionalAlternateEncoding, - // first. The fix for workitem 6513 tried to use UTF8 - // only as necessary, but that is impossible to test - // for, in this direction. There's no way to know what - // characters the already-encoded bytes refer - // to. Therefore, must do what the user tells us. - - string s1 = zf.AlternateEncoding.GetString(block, 0, block.Length); - zf.Comment = s1; - } - } - - - // private static bool BlocksAreEqual(byte[] a, byte[] b) - // { - // if (a.Length != b.Length) return false; - // for (int i = 0; i < a.Length; i++) - // { - // if (a[i] != b[i]) return false; - // } - // return true; - // } - - - - /// - /// Checks the given file to see if it appears to be a valid zip file. - /// - /// - /// - /// - /// Calling this method is equivalent to calling with the testExtract parameter set to false. - /// - /// - /// - /// The file to check. - /// true if the file appears to be a zip file. - public static bool IsZipFile(string fileName) - { - return IsZipFile(fileName, false); - } - - - /// - /// Checks a file to see if it is a valid zip file. - /// - /// - /// - /// - /// This method opens the specified zip file, reads in the zip archive, - /// verifying the ZIP metadata as it reads. - /// - /// - /// - /// If everything succeeds, then the method returns true. If anything fails - - /// for example if an incorrect signature or CRC is found, indicating a - /// corrupt file, the the method returns false. This method also returns - /// false for a file that does not exist. - /// - /// - /// - /// If is true, as part of its check, this - /// method reads in the content for each entry, expands it, and checks CRCs. - /// This provides an additional check beyond verifying the zip header and - /// directory data. - /// - /// - /// - /// If is true, and if any of the zip entries - /// are protected with a password, this method will return false. If you want - /// to verify a ZipFile that has entries which are protected with a - /// password, you will need to do that manually. - /// - /// - /// - /// - /// The zip file to check. - /// true if the caller wants to extract each entry. - /// true if the file contains a valid zip file. - public static bool IsZipFile(string fileName, bool testExtract) - { - bool result = false; - try - { - if (!File.Exists(fileName)) return false; - - using (var s = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) - { - result = IsZipFile(s, testExtract); - } - } - catch (IOException) { } - catch (ZipException) { } - return result; - } - - - /// - /// Checks a stream to see if it contains a valid zip archive. - /// - /// - /// - /// - /// This method reads the zip archive contained in the specified stream, verifying - /// the ZIP metadata as it reads. If testExtract is true, this method also extracts - /// each entry in the archive, dumping all the bits into . - /// - /// - /// - /// If everything succeeds, then the method returns true. If anything fails - - /// for example if an incorrect signature or CRC is found, indicating a corrupt - /// file, the the method returns false. This method also returns false for a - /// file that does not exist. - /// - /// - /// - /// If testExtract is true, this method reads in the content for each - /// entry, expands it, and checks CRCs. This provides an additional check - /// beyond verifying the zip header data. - /// - /// - /// - /// If testExtract is true, and if any of the zip entries are protected - /// with a password, this method will return false. If you want to verify a - /// ZipFile that has entries which are protected with a password, you will need - /// to do that manually. - /// - /// - /// - /// - /// - /// The stream to check. - /// true if the caller wants to extract each entry. - /// true if the stream contains a valid zip archive. - public static bool IsZipFile(Stream stream, bool testExtract) - { - if (stream == null) - throw new ArgumentNullException("stream"); - - bool result = false; - try - { - if (!stream.CanRead) return false; - - var bitBucket = Stream.Null; - - using (ZipFile zip1 = ZipFile.Read(stream, null, null, null)) - { - if (testExtract) - { - foreach (var e in zip1) - { - if (!e.IsDirectory) - { - e.Extract(bitBucket); - } - } - } - } - result = true; - } - catch (IOException) { } - catch (ZipException) { } - return result; - } - - - - - } - -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Save.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Save.cs deleted file mode 100644 index 9b077518..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Save.cs +++ /dev/null @@ -1,964 +0,0 @@ -// ZipFile.Save.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2009 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-August-05 13:31:23> -// -// ------------------------------------------------------------------ -// -// This module defines the methods for Save operations on zip files. -// -// ------------------------------------------------------------------ -// - - -using System; -using System.IO; -using System.Collections.Generic; - -namespace Ionic.Zip -{ - - public partial class ZipFile - { - - /// - /// Delete file with retry on UnauthorizedAccessException. - /// - /// - /// - /// - /// When calling File.Delete() on a file that has been "recently" - /// created, the call sometimes fails with - /// UnauthorizedAccessException. This method simply retries the Delete 3 - /// times with a sleep between tries. - /// - /// - /// - /// the name of the file to be deleted - private void DeleteFileWithRetry(string filename) - { - bool done = false; - int nRetries = 3; - for (int i=0; i < nRetries && !done; i++) - { - try - { - File.Delete(filename); - done = true; - } - catch (System.UnauthorizedAccessException) - { - Console.WriteLine("************************************************** Retry delete."); - System.Threading.Thread.Sleep(200+i*200); - } - } - } - - - /// - /// Saves the Zip archive to a file, specified by the Name property of the - /// ZipFile. - /// - /// - /// - /// - /// The ZipFile instance is written to storage, typically a zip file - /// in a filesystem, only when the caller calls Save. In the typical - /// case, the Save operation writes the zip content to a temporary file, and - /// then renames the temporary file to the desired name. If necessary, this - /// method will delete a pre-existing file before the rename. - /// - /// - /// - /// The property is specified either explicitly, - /// or implicitly using one of the parameterized ZipFile constructors. For - /// COM Automation clients, the Name property must be set explicitly, - /// because COM Automation clients cannot call parameterized constructors. - /// - /// - /// - /// When using a filesystem file for the Zip output, it is possible to call - /// Save multiple times on the ZipFile instance. With each - /// call the zip content is re-written to the same output file. - /// - /// - /// - /// Data for entries that have been added to the ZipFile instance is - /// written to the output when the Save method is called. This means - /// that the input streams for those entries must be available at the time - /// the application calls Save. If, for example, the application - /// adds entries with AddEntry using a dynamically-allocated - /// MemoryStream, the memory stream must not have been disposed - /// before the call to Save. See the property for more discussion of the - /// availability requirements of the input stream for an entry, and an - /// approach for providing just-in-time stream lifecycle management. - /// - /// - /// - /// - /// - /// - /// - /// Thrown if you haven't specified a location or stream for saving the zip, - /// either in the constructor or by setting the Name property, or if you try - /// to save a regular zip archive to a filename with a .exe extension. - /// - /// - /// - /// Thrown if is non-zero, and the number - /// of segments that would be generated for the spanned zip file during the - /// save operation exceeds 99. If this happens, you need to increase the - /// segment size. - /// - /// - public void Save() - { - try - { - bool thisSaveUsedZip64 = false; - _saveOperationCanceled = false; - _numberOfSegmentsForMostRecentSave = 0; - OnSaveStarted(); - - if (WriteStream == null) - throw new BadStateException("You haven't specified where to save the zip."); - - if (_name != null && _name.EndsWith(".exe") && !_SavingSfx) - throw new BadStateException("You specified an EXE for a plain zip file."); - - // check if modified, before saving. - if (!_contentsChanged) - { - OnSaveCompleted(); - if (Verbose) StatusMessageTextWriter.WriteLine("No save is necessary...."); - return; - } - - Reset(true); - - if (Verbose) StatusMessageTextWriter.WriteLine("saving...."); - - // validate the number of entries - if (_entries.Count >= 0xFFFF && _zip64 == Zip64Option.Never) - throw new ZipException("The number of entries is 65535 or greater. Consider setting the UseZip64WhenSaving property on the ZipFile instance."); - - - // write an entry in the zip for each file - int n = 0; - // workitem 9831 - ICollection c = (SortEntriesBeforeSaving) ? EntriesSorted : Entries; - foreach (ZipEntry e in c) // _entries.Values - { - OnSaveEntry(n, e, true); - e.Write(WriteStream); - if (_saveOperationCanceled) - break; - - n++; - OnSaveEntry(n, e, false); - if (_saveOperationCanceled) - break; - - // Some entries can be skipped during the save. - if (e.IncludedInMostRecentSave) - thisSaveUsedZip64 |= e.OutputUsedZip64.Value; - } - - - - if (_saveOperationCanceled) - return; - - var zss = WriteStream as ZipSegmentedStream; - - _numberOfSegmentsForMostRecentSave = (zss!=null) - ? zss.CurrentSegment - : 1; - - bool directoryNeededZip64 = - ZipOutput.WriteCentralDirectoryStructure - (WriteStream, - c, - _numberOfSegmentsForMostRecentSave, - _zip64, - Comment, - new ZipContainer(this)); - - OnSaveEvent(ZipProgressEventType.Saving_AfterSaveTempArchive); - - _hasBeenSaved = true; - _contentsChanged = false; - - thisSaveUsedZip64 |= directoryNeededZip64; - _OutputUsesZip64 = new Nullable(thisSaveUsedZip64); - - - // do the rename as necessary - if (_name != null && - (_temporaryFileName!=null || zss != null)) - { - // _temporaryFileName may remain null if we are writing to a stream. - // only close the stream if there is a file behind it. -#if NETCF - WriteStream.Close(); -#else - WriteStream.Dispose(); -#endif - if (_saveOperationCanceled) - return; - - if (_fileAlreadyExists && this._readstream != null) - { - // This means we opened and read a zip file. - // If we are now saving to the same file, we need to close the - // orig file, first. - this._readstream.Close(); - this._readstream = null; - // the archiveStream for each entry needs to be null - foreach (var e in c) - { - var zss1 = e._archiveStream as ZipSegmentedStream; - if (zss1 != null) -#if NETCF - zss1.Close(); -#else - zss1.Dispose(); -#endif - e._archiveStream = null; - } - } - - string tmpName = null; - if (File.Exists(_name)) - { - // the steps: - // - // 1. Delete tmpName - // 2. move existing zip to tmpName - // 3. rename (File.Move) working file to name of existing zip - // 4. delete tmpName - // - // This series of steps avoids the exception, - // System.IO.IOException: - // "Cannot create a file when that file already exists." - // - // Cannot just call File.Replace() here because - // there is a possibility that the TEMP volume is different - // that the volume for the final file (c:\ vs d:\). - // So we need to do a Delete+Move pair. - // - // But, when doing the delete, Windows allows a process to - // delete the file, even though it is held open by, say, a - // virus scanner. It gets internally marked as "delete - // pending". The file does not actually get removed from the - // file system, it is still there after the File.Delete - // call. - // - // Therefore, we need to move the existing zip, which may be - // held open, to some other name. Then rename our working - // file to the desired name, then delete (possibly delete - // pending) the "other name". - // - // Ideally this would be transactional. It's possible that the - // delete succeeds and the move fails. Lacking transactions, if - // this kind of failure happens, we're hosed, and this logic will - // throw on the next File.Move(). - // - //File.Delete(_name); - // workitem 10447 -#if NETCF || SILVERLIGHT - tmpName = _name + "." + SharedUtilities.GenerateRandomStringImpl(8,0) + ".tmp"; -#else - tmpName = _name + "." + Path.GetRandomFileName(); -#endif - if (File.Exists(tmpName)) - DeleteFileWithRetry(tmpName); - File.Move(_name, tmpName); - } - - OnSaveEvent(ZipProgressEventType.Saving_BeforeRenameTempArchive); - File.Move((zss != null) ? zss.CurrentTempName : _temporaryFileName, - _name); - - OnSaveEvent(ZipProgressEventType.Saving_AfterRenameTempArchive); - - if (tmpName != null) - { - try - { - // not critical - if (File.Exists(tmpName)) - File.Delete(tmpName); - } - catch - { - // don't care about exceptions here. - } - - } - _fileAlreadyExists = true; - } - - NotifyEntriesSaveComplete(c); - OnSaveCompleted(); - _JustSaved = true; - } - - // workitem 5043 - finally - { - CleanupAfterSaveOperation(); - } - - return; - } - - - - private static void NotifyEntriesSaveComplete(ICollection c) - { - foreach (ZipEntry e in c) - { - e.NotifySaveComplete(); - } - } - - - private void RemoveTempFile() - { - try - { - if (File.Exists(_temporaryFileName)) - { - File.Delete(_temporaryFileName); - } - } - catch (IOException ex1) - { - if (Verbose) - StatusMessageTextWriter.WriteLine("ZipFile::Save: could not delete temp file: {0}.", ex1.Message); - } - } - - - private void CleanupAfterSaveOperation() - { - if (_name != null) - { - // close the stream if there is a file behind it. - if (_writestream != null) - { - try - { - // workitem 7704 -#if NETCF - _writestream.Close(); -#else - _writestream.Dispose(); -#endif - } - catch (System.IO.IOException) { } - } - _writestream = null; - - if (_temporaryFileName != null) - { - RemoveTempFile(); - _temporaryFileName = null; - } - } - } - - - /// - /// Save the file to a new zipfile, with the given name. - /// - /// - /// - /// - /// This method allows the application to explicitly specify the name of the zip - /// file when saving. Use this when creating a new zip file, or when - /// updating a zip archive. - /// - /// - /// - /// An application can also save a zip archive in several places by calling this - /// method multiple times in succession, with different filenames. - /// - /// - /// - /// The ZipFile instance is written to storage, typically a zip file in a - /// filesystem, only when the caller calls Save. The Save operation writes - /// the zip content to a temporary file, and then renames the temporary file - /// to the desired name. If necessary, this method will delete a pre-existing file - /// before the rename. - /// - /// - /// - /// - /// - /// Thrown if you specify a directory for the filename. - /// - /// - /// - /// The name of the zip archive to save to. Existing files will - /// be overwritten with great prejudice. - /// - /// - /// - /// This example shows how to create and Save a zip file. - /// - /// using (ZipFile zip = new ZipFile()) - /// { - /// zip.AddDirectory(@"c:\reports\January"); - /// zip.Save("January.zip"); - /// } - /// - /// - /// - /// Using zip As New ZipFile() - /// zip.AddDirectory("c:\reports\January") - /// zip.Save("January.zip") - /// End Using - /// - /// - /// - /// - /// - /// This example shows how to update a zip file. - /// - /// using (ZipFile zip = ZipFile.Read("ExistingArchive.zip")) - /// { - /// zip.AddFile("NewData.csv"); - /// zip.Save("UpdatedArchive.zip"); - /// } - /// - /// - /// - /// Using zip As ZipFile = ZipFile.Read("ExistingArchive.zip") - /// zip.AddFile("NewData.csv") - /// zip.Save("UpdatedArchive.zip") - /// End Using - /// - /// - /// - public void Save(String fileName) - { - // Check for the case where we are re-saving a zip archive - // that was originally instantiated with a stream. In that case, - // the _name will be null. If so, we set _writestream to null, - // which insures that we'll cons up a new WriteStream (with a filesystem - // file backing it) in the Save() method. - if (_name == null) - _writestream = null; - - else _readName = _name; // workitem 13915 - - _name = fileName; - if (Directory.Exists(_name)) - throw new ZipException("Bad Directory", new System.ArgumentException("That name specifies an existing directory. Please specify a filename.", "fileName")); - _contentsChanged = true; - _fileAlreadyExists = File.Exists(_name); - Save(); - } - - - /// - /// Save the zip archive to the specified stream. - /// - /// - /// - /// - /// The ZipFile instance is written to storage - typically a zip file - /// in a filesystem, but using this overload, the storage can be anything - /// accessible via a writable stream - only when the caller calls Save. - /// - /// - /// - /// Use this method to save the zip content to a stream directly. A common - /// scenario is an ASP.NET application that dynamically generates a zip file - /// and allows the browser to download it. The application can call - /// Save(Response.OutputStream) to write a zipfile directly to the - /// output stream, without creating a zip file on the disk on the ASP.NET - /// server. - /// - /// - /// - /// Be careful when saving a file to a non-seekable stream, including - /// Response.OutputStream. When DotNetZip writes to a non-seekable - /// stream, the zip archive is formatted in such a way that may not be - /// compatible with all zip tools on all platforms. It's a perfectly legal - /// and compliant zip file, but some people have reported problems opening - /// files produced this way using the Mac OS archive utility. - /// - /// - /// - /// - /// - /// - /// This example saves the zipfile content into a MemoryStream, and - /// then gets the array of bytes from that MemoryStream. - /// - /// - /// using (var zip = new Ionic.Zip.ZipFile()) - /// { - /// zip.CompressionLevel= Ionic.Zlib.CompressionLevel.BestCompression; - /// zip.Password = "VerySecret."; - /// zip.Encryption = EncryptionAlgorithm.WinZipAes128; - /// zip.AddFile(sourceFileName); - /// MemoryStream output = new MemoryStream(); - /// zip.Save(output); - /// - /// byte[] zipbytes = output.ToArray(); - /// } - /// - /// - /// - /// - /// - /// This example shows a pitfall you should avoid. DO NOT read - /// from a stream, then try to save to the same stream. DO - /// NOT DO THIS: - /// - /// - /// - /// using (var fs = new FileSteeam(filename, FileMode.Open)) - /// { - /// using (var zip = Ionic.Zip.ZipFile.Read(inputStream)) - /// { - /// zip.AddEntry("Name1.txt", "this is the content"); - /// zip.Save(inputStream); // NO NO NO!! - /// } - /// } - /// - /// - /// - /// Better like this: - /// - /// - /// - /// using (var zip = Ionic.Zip.ZipFile.Read(filename)) - /// { - /// zip.AddEntry("Name1.txt", "this is the content"); - /// zip.Save(); // YES! - /// } - /// - /// - /// - /// - /// - /// The System.IO.Stream to write to. It must be - /// writable. If you created the ZipFile instanct by calling - /// ZipFile.Read(), this stream must not be the same stream - /// you passed to ZipFile.Read(). - /// - public void Save(Stream outputStream) - { - if (outputStream == null) - throw new ArgumentNullException("outputStream"); - if (!outputStream.CanWrite) - throw new ArgumentException("Must be a writable stream.", "outputStream"); - - // if we had a filename to save to, we are now obliterating it. - _name = null; - - _writestream = new CountingStream(outputStream); - - _contentsChanged = true; - _fileAlreadyExists = false; - Save(); - } - - - } - - - - internal static class ZipOutput - { - public static bool WriteCentralDirectoryStructure(Stream s, - ICollection entries, - uint numSegments, - Zip64Option zip64, - String comment, - ZipContainer container) - { - var zss = s as ZipSegmentedStream; - if (zss != null) - zss.ContiguousWrite = true; - - // write to a memory stream in order to keep the - // CDR contiguous - Int64 aLength = 0; - using (var ms = new MemoryStream()) - { - foreach (ZipEntry e in entries) - { - if (e.IncludedInMostRecentSave) - { - // this writes a ZipDirEntry corresponding to the ZipEntry - e.WriteCentralDirectoryEntry(ms); - } - } - var a = ms.ToArray(); - s.Write(a, 0, a.Length); - aLength = a.Length; - } - - - // We need to keep track of the start and - // Finish of the Central Directory Structure. - - // Cannot always use WriteStream.Length or Position; some streams do - // not support these. (eg, ASP.NET Response.OutputStream) In those - // cases we have a CountingStream. - - // Also, we cannot just set Start as s.Position bfore the write, and Finish - // as s.Position after the write. In a split zip, the write may actually - // flip to the next segment. In that case, Start will be zero. But we - // don't know that til after we know the size of the thing to write. So the - // answer is to compute the directory, then ask the ZipSegmentedStream which - // segment that directory would fall in, it it were written. Then, include - // that data into the directory, and finally, write the directory to the - // output stream. - - var output = s as CountingStream; - long Finish = (output != null) ? output.ComputedPosition : s.Position; // BytesWritten - long Start = Finish - aLength; - - // need to know which segment the EOCD record starts in - UInt32 startSegment = (zss != null) - ? zss.CurrentSegment - : 0; - - Int64 SizeOfCentralDirectory = Finish - Start; - - int countOfEntries = CountEntries(entries); - - bool needZip64CentralDirectory = - zip64 == Zip64Option.Always || - countOfEntries >= 0xFFFF || - SizeOfCentralDirectory > 0xFFFFFFFF || - Start > 0xFFFFFFFF; - - byte[] a2 = null; - - // emit ZIP64 extensions as required - if (needZip64CentralDirectory) - { - if (zip64 == Zip64Option.Never) - { -#if NETCF - throw new ZipException("The archive requires a ZIP64 Central Directory. Consider enabling ZIP64 extensions."); -#else - System.Diagnostics.StackFrame sf = new System.Diagnostics.StackFrame(1); - if (sf.GetMethod().DeclaringType == typeof(ZipFile)) - throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipFile.UseZip64WhenSaving property."); - else - throw new ZipException("The archive requires a ZIP64 Central Directory. Consider setting the ZipOutputStream.EnableZip64 property."); -#endif - - } - - var a = GenZip64EndOfCentralDirectory(Start, Finish, countOfEntries, numSegments); - a2 = GenCentralDirectoryFooter(Start, Finish, zip64, countOfEntries, comment, container); - if (startSegment != 0) - { - UInt32 thisSegment = zss.ComputeSegment(a.Length + a2.Length); - int i = 16; - // number of this disk - Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4); - i += 4; - // number of the disk with the start of the central directory - //Array.Copy(BitConverter.GetBytes(startSegment), 0, a, i, 4); - Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4); - - i = 60; - // offset 60 - // number of the disk with the start of the zip64 eocd - Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4); - i += 4; - i += 8; - - // offset 72 - // total number of disks - Array.Copy(BitConverter.GetBytes(thisSegment), 0, a, i, 4); - } - s.Write(a, 0, a.Length); - } - else - a2 = GenCentralDirectoryFooter(Start, Finish, zip64, countOfEntries, comment, container); - - - // now, the regular footer - if (startSegment != 0) - { - // The assumption is the central directory is never split across - // segment boundaries. - - UInt16 thisSegment = (UInt16) zss.ComputeSegment(a2.Length); - int i = 4; - // number of this disk - Array.Copy(BitConverter.GetBytes(thisSegment), 0, a2, i, 2); - i += 2; - // number of the disk with the start of the central directory - //Array.Copy(BitConverter.GetBytes((UInt16)startSegment), 0, a2, i, 2); - Array.Copy(BitConverter.GetBytes(thisSegment), 0, a2, i, 2); - i += 2; - } - - s.Write(a2, 0, a2.Length); - - // reset the contiguous write property if necessary - if (zss != null) - zss.ContiguousWrite = false; - - return needZip64CentralDirectory; - } - - - private static System.Text.Encoding GetEncoding(ZipContainer container, string t) - { - switch (container.AlternateEncodingUsage) - { - case ZipOption.Always: - return container.AlternateEncoding; - case ZipOption.Never: - return container.DefaultEncoding; - } - - // AsNecessary is in force - var e = container.DefaultEncoding; - if (t == null) return e; - - var bytes = e.GetBytes(t); - var t2 = e.GetString(bytes,0,bytes.Length); - if (t2.Equals(t)) return e; - return container.AlternateEncoding; - } - - - - private static byte[] GenCentralDirectoryFooter(long StartOfCentralDirectory, - long EndOfCentralDirectory, - Zip64Option zip64, - int entryCount, - string comment, - ZipContainer container) - { - System.Text.Encoding encoding = GetEncoding(container, comment); - int j = 0; - int bufferLength = 22; - byte[] block = null; - Int16 commentLength = 0; - if ((comment != null) && (comment.Length != 0)) - { - block = encoding.GetBytes(comment); - commentLength = (Int16)block.Length; - } - bufferLength += commentLength; - byte[] bytes = new byte[bufferLength]; - - int i = 0; - // signature - byte[] sig = BitConverter.GetBytes(ZipConstants.EndOfCentralDirectorySignature); - Array.Copy(sig, 0, bytes, i, 4); - i+=4; - - // number of this disk - // (this number may change later) - bytes[i++] = 0; - bytes[i++] = 0; - - // number of the disk with the start of the central directory - // (this number may change later) - bytes[i++] = 0; - bytes[i++] = 0; - - // handle ZIP64 extensions for the end-of-central-directory - if (entryCount >= 0xFFFF || zip64 == Zip64Option.Always) - { - // the ZIP64 version. - for (j = 0; j < 4; j++) - bytes[i++] = 0xFF; - } - else - { - // the standard version. - // total number of entries in the central dir on this disk - bytes[i++] = (byte)(entryCount & 0x00FF); - bytes[i++] = (byte)((entryCount & 0xFF00) >> 8); - - // total number of entries in the central directory - bytes[i++] = (byte)(entryCount & 0x00FF); - bytes[i++] = (byte)((entryCount & 0xFF00) >> 8); - } - - // size of the central directory - Int64 SizeOfCentralDirectory = EndOfCentralDirectory - StartOfCentralDirectory; - - if (SizeOfCentralDirectory >= 0xFFFFFFFF || StartOfCentralDirectory >= 0xFFFFFFFF) - { - // The actual data is in the ZIP64 central directory structure - for (j = 0; j < 8; j++) - bytes[i++] = 0xFF; - } - else - { - // size of the central directory (we just get the low 4 bytes) - bytes[i++] = (byte)(SizeOfCentralDirectory & 0x000000FF); - bytes[i++] = (byte)((SizeOfCentralDirectory & 0x0000FF00) >> 8); - bytes[i++] = (byte)((SizeOfCentralDirectory & 0x00FF0000) >> 16); - bytes[i++] = (byte)((SizeOfCentralDirectory & 0xFF000000) >> 24); - - // offset of the start of the central directory (we just get the low 4 bytes) - bytes[i++] = (byte)(StartOfCentralDirectory & 0x000000FF); - bytes[i++] = (byte)((StartOfCentralDirectory & 0x0000FF00) >> 8); - bytes[i++] = (byte)((StartOfCentralDirectory & 0x00FF0000) >> 16); - bytes[i++] = (byte)((StartOfCentralDirectory & 0xFF000000) >> 24); - } - - - // zip archive comment - if ((comment == null) || (comment.Length == 0)) - { - // no comment! - bytes[i++] = (byte)0; - bytes[i++] = (byte)0; - } - else - { - // the size of our buffer defines the max length of the comment we can write - if (commentLength + i + 2 > bytes.Length) commentLength = (Int16)(bytes.Length - i - 2); - bytes[i++] = (byte)(commentLength & 0x00FF); - bytes[i++] = (byte)((commentLength & 0xFF00) >> 8); - - if (commentLength != 0) - { - // now actually write the comment itself into the byte buffer - for (j = 0; (j < commentLength) && (i + j < bytes.Length); j++) - { - bytes[i + j] = block[j]; - } - i += j; - } - } - - // s.Write(bytes, 0, i); - return bytes; - } - - - - private static byte[] GenZip64EndOfCentralDirectory(long StartOfCentralDirectory, - long EndOfCentralDirectory, - int entryCount, - uint numSegments) - { - const int bufferLength = 12 + 44 + 20; - - byte[] bytes = new byte[bufferLength]; - - int i = 0; - // signature - byte[] sig = BitConverter.GetBytes(ZipConstants.Zip64EndOfCentralDirectoryRecordSignature); - Array.Copy(sig, 0, bytes, i, 4); - i+=4; - - // There is a possibility to include "Extensible" data in the zip64 - // end-of-central-dir record. I cannot figure out what it might be used to - // store, so the size of this record is always fixed. Maybe it is used for - // strong encryption data? That is for another day. - long DataSize = 44; - Array.Copy(BitConverter.GetBytes(DataSize), 0, bytes, i, 8); - i += 8; - - // offset 12 - // VersionMadeBy = 45; - bytes[i++] = 45; - bytes[i++] = 0x00; - - // VersionNeededToExtract = 45; - bytes[i++] = 45; - bytes[i++] = 0x00; - - // offset 16 - // number of the disk, and the disk with the start of the central dir. - // (this may change later) - for (int j = 0; j < 8; j++) - bytes[i++] = 0x00; - - // offset 24 - long numberOfEntries = entryCount; - Array.Copy(BitConverter.GetBytes(numberOfEntries), 0, bytes, i, 8); - i += 8; - Array.Copy(BitConverter.GetBytes(numberOfEntries), 0, bytes, i, 8); - i += 8; - - // offset 40 - Int64 SizeofCentraldirectory = EndOfCentralDirectory - StartOfCentralDirectory; - Array.Copy(BitConverter.GetBytes(SizeofCentraldirectory), 0, bytes, i, 8); - i += 8; - Array.Copy(BitConverter.GetBytes(StartOfCentralDirectory), 0, bytes, i, 8); - i += 8; - - // offset 56 - // now, the locator - // signature - sig = BitConverter.GetBytes(ZipConstants.Zip64EndOfCentralDirectoryLocatorSignature); - Array.Copy(sig, 0, bytes, i, 4); - i+=4; - - // offset 60 - // number of the disk with the start of the zip64 eocd - // (this will change later) (it will?) - uint x2 = (numSegments==0)?0:(uint)(numSegments-1); - Array.Copy(BitConverter.GetBytes(x2), 0, bytes, i, 4); - i+=4; - - // offset 64 - // relative offset of the zip64 eocd - Array.Copy(BitConverter.GetBytes(EndOfCentralDirectory), 0, bytes, i, 8); - i += 8; - - // offset 72 - // total number of disks - // (this will change later) - Array.Copy(BitConverter.GetBytes(numSegments), 0, bytes, i, 4); - i+=4; - - return bytes; - } - - - - private static int CountEntries(ICollection _entries) - { - // Cannot just emit _entries.Count, because some of the entries - // may have been skipped. - int count = 0; - foreach (var entry in _entries) - if (entry.IncludedInMostRecentSave) count++; - return count; - } - - - - - } -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.SaveSelfExtractor.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.SaveSelfExtractor.cs deleted file mode 100644 index 9de5dc82..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.SaveSelfExtractor.cs +++ /dev/null @@ -1,1101 +0,0 @@ -// ZipFile.saveSelfExtractor.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2008-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-August-10 19:22:46> -// -// ------------------------------------------------------------------ -// -// This is a the source module that implements the stuff for saving to a -// self-extracting Zip archive. -// -// ZipFile is set up as a "partial class" - defined in multiple .cs source modules. -// This is one of the source modules for the ZipFile class. -// -// Here's the design: The self-extracting zip file is just a regular managed EXE -// file, with embedded resources. The managed code logic instantiates a ZipFile, and -// then extracts each entry. The embedded resources include the zip archive content, -// as well as the Zip library itself. The latter is required so that self-extracting -// can work on any machine, whether or not it has the DotNetZip library installed on -// it. -// -// What we need to do is create the animal I just described, within a method on the -// ZipFile class. This source module provides that capability. The method is -// SaveSelfExtractor(). -// -// The way the method works: it uses the programmatic interface to the csc.exe -// compiler, Microsoft.CSharp.CSharpCodeProvider, to compile "boilerplate" -// extraction logic into a new assembly. As part of that compile, we embed within -// that assembly the zip archive itself, as well as the Zip library. -// -// Therefore we need to first save to a temporary zip file, then produce the exe. -// -// There are a few twists. -// -// The Visual Studio Project structure is a little weird. There are code files -// that ARE NOT compiled during a normal build of the VS Solution. They are -// marked as embedded resources. These are the various "boilerplate" modules that -// are used in the self-extractor. These modules are: WinFormsSelfExtractorStub.cs -// WinFormsSelfExtractorStub.Designer.cs CommandLineSelfExtractorStub.cs -// PasswordDialog.cs PasswordDialog.Designer.cs -// -// At design time, if you want to modify the way the GUI looks, you have to -// mark those modules to have a "compile" build action. Then tweak em, test, -// etc. Then again mark them as "Embedded resource". -// -// ------------------------------------------------------------------ - -using System; -using System.Reflection; -using System.IO; -using System.Collections.Generic; - - -namespace Ionic.Zip -{ -#if !NO_SFX - /// - /// An enum that provides the different self-extractor flavors - /// - public enum SelfExtractorFlavor - { - /// - /// A self-extracting zip archive that runs from the console or - /// command line. - /// - ConsoleApplication = 0, - - /// - /// A self-extracting zip archive that presents a graphical user - /// interface when it is executed. - /// - WinFormsApplication, - } - - /// - /// The options for generating a self-extracting archive. - /// - public class SelfExtractorSaveOptions - { - /// - /// The type of SFX to create. - /// - public SelfExtractorFlavor Flavor - { - get; - set; - } - - /// - /// The command to run after extraction. - /// - /// - /// - /// - /// This is optional. Leave it empty (null in C# or Nothing in - /// VB) to run no command after extraction. - /// - /// - /// - /// If it is non-empty, the SFX will execute the command specified in this - /// string on the user's machine, and using the extract directory as the - /// working directory for the process, after unpacking the archive. The - /// program to execute can include a path, if you like. If you want to execute - /// a program that accepts arguments, specify the program name, followed by a - /// space, and then the arguments for the program, each separated by a space, - /// just as you would on a normal command line. Example: program.exe arg1 - /// arg2. The string prior to the first space will be taken as the - /// program name, and the string following the first space specifies the - /// arguments to the program. - /// - /// - /// - /// If you want to execute a program that has a space in the name or path of - /// the file, surround the program name in double-quotes. The first character - /// of the command line should be a double-quote character, and there must be - /// a matching double-quote following the end of the program file name. Any - /// optional arguments to the program follow that, separated by - /// spaces. Example: "c:\project files\program name.exe" arg1 arg2. - /// - /// - /// - /// If the flavor of the SFX is SelfExtractorFlavor.ConsoleApplication, - /// then the SFX starts a new process, using this string as the post-extract - /// command line. The SFX waits for the process to exit. The exit code of - /// the post-extract command line is returned as the exit code of the - /// command-line self-extractor exe. A non-zero exit code is typically used to - /// indicated a failure by the program. In the case of an SFX, a non-zero exit - /// code may indicate a failure during extraction, OR, it may indicate a - /// failure of the run-after-extract program if specified, OR, it may indicate - /// the run-after-extract program could not be fuond. There is no way to - /// distinguish these conditions from the calling shell, aside from parsing - /// the output of the SFX. If you have Quiet set to true, you may not - /// see error messages, if a problem occurs. - /// - /// - /// - /// If the flavor of the SFX is - /// SelfExtractorFlavor.WinFormsApplication, then the SFX starts a new - /// process, using this string as the post-extract command line, and using the - /// extract directory as the working directory for the process. The SFX does - /// not wait for the command to complete, and does not check the exit code of - /// the program. If the run-after-extract program cannot be fuond, a message - /// box is displayed indicating that fact. - /// - /// - /// - /// You can specify environment variables within this string, with a format like - /// %NAME%. The value of these variables will be expanded at the time - /// the SFX is run. Example: %WINDIR%\system32\xcopy.exe may expand at - /// runtime to c:\Windows\System32\xcopy.exe. - /// - /// - /// - /// By combining this with the RemoveUnpackedFilesAfterExecute - /// flag, you can create an SFX that extracts itself, runs a file that - /// was extracted, then deletes all the files that were extracted. If - /// you want it to run "invisibly" then set Flavor to - /// SelfExtractorFlavor.ConsoleApplication, and set Quiet - /// to true. The user running such an EXE will see a console window - /// appear, then disappear quickly. You may also want to specify the - /// default extract location, with DefaultExtractDirectory. - /// - /// - /// - /// If you set Flavor to - /// SelfExtractorFlavor.WinFormsApplication, and set Quiet to - /// true, then a GUI with progressbars is displayed, but it is - /// "non-interactive" - it accepts no input from the user. Instead the SFX - /// just automatically unpacks and exits. - /// - /// - /// - public String PostExtractCommandLine - { - get; - set; - } - - /// - /// The default extract directory the user will see when - /// running the self-extracting archive. - /// - /// - /// - /// - /// Passing null (or Nothing in VB) here will cause the Self Extractor to use - /// the the user's personal directory () for the default extract - /// location. - /// - /// - /// - /// This is only a default location. The actual extract location will be - /// settable on the command line when the SFX is executed. - /// - /// - /// - /// You can specify environment variables within this string, - /// with %NAME%. The value of these variables will be - /// expanded at the time the SFX is run. Example: - /// %USERPROFILE%\Documents\unpack may expand at runtime to - /// c:\users\melvin\Documents\unpack. - /// - /// - public String DefaultExtractDirectory - { - get; - set; - } - - /// - /// The name of an .ico file in the filesystem to use for the application icon - /// for the generated SFX. - /// - /// - /// - /// - /// Normally, DotNetZip will embed an "zipped folder" icon into the generated - /// SFX. If you prefer to use a different icon, you can specify it here. It - /// should be a .ico file. This file is passed as the /win32icon - /// option to the csc.exe compiler when constructing the SFX file. - /// - /// - /// - public string IconFile - { - get; - set; - } - - /// - /// Whether the ConsoleApplication SFX will be quiet during extraction. - /// - /// - /// - /// - /// This option affects the way the generated SFX runs. By default it is - /// false. When you set it to true,... - /// - /// - /// - /// - /// Flavor - /// Behavior - /// - /// - /// - /// ConsoleApplication - /// no messages will be emitted during successful - /// operation. Double-clicking the SFX in Windows - /// Explorer or as an attachment in an email will cause a console - /// window to appear briefly, before it disappears. If you run the - /// ConsoleApplication SFX from the cmd.exe prompt, it runs as a - /// normal console app; by default, because it is quiet, it displays - /// no messages to the console. If you pass the -v+ command line - /// argument to the Console SFX when you run it, you will get verbose - /// messages to the console. - /// - /// - /// - /// - /// WinFormsApplication - /// the SFX extracts automatically when the application - /// is launched, with no additional user input. - /// - /// - /// - /// - /// - /// - /// When you set it to false,... - /// - /// - /// - /// - /// Flavor - /// Behavior - /// - /// - /// - /// ConsoleApplication - /// the extractor will emit a - /// message to the console for each entry extracted. - /// - /// When double-clicking to launch the SFX, the console window will - /// remain, and the SFX will emit a message for each file as it - /// extracts. The messages fly by quickly, they won't be easily - /// readable, unless the extracted files are fairly large. - /// - /// - /// - /// - /// - /// WinFormsApplication - /// the SFX presents a forms UI and allows the user to select - /// options before extracting. - /// - /// - /// - /// - /// - /// - public bool Quiet - { - get; - set; - } - - - /// - /// Specify what the self-extractor will do when extracting an entry - /// would overwrite an existing file. - /// - /// - /// - /// The default behavvior is to Throw. - /// - /// - public Ionic.Zip.ExtractExistingFileAction ExtractExistingFile - { - get; - set; - } - - - /// - /// Whether to remove the files that have been unpacked, after executing the - /// PostExtractCommandLine. - /// - /// - /// - /// - /// If true, and if there is a - /// PostExtractCommandLine, and if the command runs successfully, - /// then the files that the SFX unpacked will be removed, afterwards. If - /// the command does not complete successfully (non-zero return code), - /// that is interpreted as a failure, and the extracted files will not be - /// removed. - /// - /// - /// - /// Setting this flag, and setting Flavor to - /// SelfExtractorFlavor.ConsoleApplication, and setting Quiet to - /// true, results in an SFX that extracts itself, runs a file that was - /// extracted, then deletes all the files that were extracted, with no - /// intervention by the user. You may also want to specify the default - /// extract location, with DefaultExtractDirectory. - /// - /// - /// - public bool RemoveUnpackedFilesAfterExecute - { - get; - set; - } - - - /// - /// The file version number to embed into the generated EXE. It will show up, for - /// example, during a mouseover in Windows Explorer. - /// - /// - public Version FileVersion - { - get; - set; - } - - /// - /// The product version to embed into the generated EXE. It will show up, for - /// example, during a mouseover in Windows Explorer. - /// - /// - /// - /// You can use any arbitrary string, but a human-readable version number is - /// recommended. For example "v1.2 alpha" or "v4.2 RC2". If you specify nothing, - /// then there is no product version embedded into the EXE. - /// - /// - public String ProductVersion - { - get; - set; - } - - /// - /// The copyright notice, if any, to embed into the generated EXE. - /// - /// - /// - /// It will show up, for example, while viewing properties of the file in - /// Windows Explorer. You can use any arbitrary string, but typically you - /// want something like "Copyright © Dino Chiesa 2011". - /// - /// - public String Copyright - { - get; - set; - } - - - /// - /// The description to embed into the generated EXE. - /// - /// - /// - /// Use any arbitrary string. This text will be displayed during a - /// mouseover in Windows Explorer. If you specify nothing, then the string - /// "DotNetZip SFX Archive" is embedded into the EXE as the description. - /// - /// - public String Description - { - get; - set; - } - - /// - /// The product name to embed into the generated EXE. - /// - /// - /// - /// Use any arbitrary string. This text will be displayed - /// while viewing properties of the EXE file in - /// Windows Explorer. - /// - /// - public String ProductName - { - get; - set; - } - - /// - /// The title to display in the Window of a GUI SFX, while it extracts. - /// - /// - /// - /// - /// By default the title show in the GUI window of a self-extractor - /// is "DotNetZip Self-extractor (http://DotNetZip.codeplex.com/)". - /// You can change that by setting this property before saving the SFX. - /// - /// - /// - /// This property has an effect only when producing a Self-extractor - /// of flavor SelfExtractorFlavor.WinFormsApplication. - /// - /// - /// - public String SfxExeWindowTitle - { - // workitem 12608 - get; - set; - } - - /// - /// Additional options for the csc.exe compiler, when producing the SFX - /// EXE. - /// - /// - public string AdditionalCompilerSwitches - { - get; set; - } - } - - - - - partial class ZipFile - { - class ExtractorSettings - { - public SelfExtractorFlavor Flavor; - public List ReferencedAssemblies; - public List CopyThroughResources; - public List ResourcesToCompile; - } - - - private static ExtractorSettings[] SettingsList = { - new ExtractorSettings() { - Flavor = SelfExtractorFlavor.WinFormsApplication, - ReferencedAssemblies= new List{ - "System.dll", "System.Windows.Forms.dll", "System.Drawing.dll"}, - CopyThroughResources = new List{ - "Ionic.Zip.WinFormsSelfExtractorStub.resources", - "Ionic.Zip.Forms.PasswordDialog.resources", - "Ionic.Zip.Forms.ZipContentsDialog.resources"}, - ResourcesToCompile = new List{ - "WinFormsSelfExtractorStub.cs", - "WinFormsSelfExtractorStub.Designer.cs", // .Designer.cs? - "PasswordDialog.cs", - "PasswordDialog.Designer.cs", //.Designer.cs" - "ZipContentsDialog.cs", - "ZipContentsDialog.Designer.cs", //.Designer.cs" - "FolderBrowserDialogEx.cs", - } - }, - new ExtractorSettings() { - Flavor = SelfExtractorFlavor.ConsoleApplication, - ReferencedAssemblies= new List { "System.dll", }, - CopyThroughResources = null, - ResourcesToCompile = new List{"CommandLineSelfExtractorStub.cs"} - } - }; - - - - //string _defaultExtractLocation; - //string _postExtractCmdLine; - // string _SetDefaultLocationCode = - // "namespace Ionic.Zip { public partial class WinFormsSelfExtractorStub { partial void _SetDefaultExtractLocation() {" + - // " txtExtractDirectory.Text = \"@@VALUE\"; } }}"; - - - - /// - /// Saves the ZipFile instance to a self-extracting zip archive. - /// - /// - /// - /// - /// - /// The generated exe image will execute on any machine that has the .NET - /// Framework 2.0 installed on it. The generated exe image is also a - /// valid ZIP file, readable with DotNetZip or another Zip library or tool - /// such as WinZip. - /// - /// - /// - /// There are two "flavors" of self-extracting archive. The - /// WinFormsApplication version will pop up a GUI and allow the - /// user to select a target directory into which to extract. There's also - /// a checkbox allowing the user to specify to overwrite existing files, - /// and another checkbox to allow the user to request that Explorer be - /// opened to see the extracted files after extraction. The other flavor - /// is ConsoleApplication. A self-extractor generated with that - /// flavor setting will run from the command line. It accepts command-line - /// options to set the overwrite behavior, and to specify the target - /// extraction directory. - /// - /// - /// - /// There are a few temporary files created during the saving to a - /// self-extracting zip. These files are created in the directory pointed - /// to by , which defaults to . These temporary files are - /// removed upon successful completion of this method. - /// - /// - /// - /// When a user runs the WinForms SFX, the user's personal directory (Environment.SpecialFolder.Personal) - /// will be used as the default extract location. If you want to set the - /// default extract location, you should use the other overload of - /// SaveSelfExtractor()/ The user who runs the SFX will have the - /// opportunity to change the extract directory before extracting. When - /// the user runs the Command-Line SFX, the user must explicitly specify - /// the directory to which to extract. The .NET Framework 2.0 is required - /// on the computer when the self-extracting archive is run. - /// - /// - /// - /// NB: This method is not available in the version of DotNetZip build for - /// the .NET Compact Framework, nor in the "Reduced" DotNetZip library. - /// - /// - /// - /// - /// - /// - /// string DirectoryPath = "c:\\Documents\\Project7"; - /// using (ZipFile zip = new ZipFile()) - /// { - /// zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)); - /// zip.Comment = "This will be embedded into a self-extracting console-based exe"; - /// zip.SaveSelfExtractor("archive.exe", SelfExtractorFlavor.ConsoleApplication); - /// } - /// - /// - /// Dim DirectoryPath As String = "c:\Documents\Project7" - /// Using zip As New ZipFile() - /// zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)) - /// zip.Comment = "This will be embedded into a self-extracting console-based exe" - /// zip.SaveSelfExtractor("archive.exe", SelfExtractorFlavor.ConsoleApplication) - /// End Using - /// - /// - /// - /// - /// a pathname, possibly fully qualified, to be created. Typically it - /// will end in an .exe extension. - /// - /// Indicates whether a Winforms or Console self-extractor is - /// desired. - public void SaveSelfExtractor(string exeToGenerate, SelfExtractorFlavor flavor) - { - SelfExtractorSaveOptions options = new SelfExtractorSaveOptions(); - options.Flavor = flavor; - SaveSelfExtractor(exeToGenerate, options); - } - - - - /// - /// Saves the ZipFile instance to a self-extracting zip archive, using - /// the specified save options. - /// - /// - /// - /// - /// This method saves a self extracting archive, using the specified save - /// options. These options include the flavor of the SFX, the default extract - /// directory, the icon file, and so on. See the documentation - /// for for more - /// details. - /// - /// - /// - /// The user who runs the SFX will have the opportunity to change the extract - /// directory before extracting. If at the time of extraction, the specified - /// directory does not exist, the SFX will create the directory before - /// extracting the files. - /// - /// - /// - /// - /// - /// This example saves a WinForms-based self-extracting archive EXE that - /// will use c:\ExtractHere as the default extract location. The C# code - /// shows syntax for .NET 3.0, which uses an object initializer for - /// the SelfExtractorOptions object. - /// - /// string DirectoryPath = "c:\\Documents\\Project7"; - /// using (ZipFile zip = new ZipFile()) - /// { - /// zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)); - /// zip.Comment = "This will be embedded into a self-extracting WinForms-based exe"; - /// var options = new SelfExtractorOptions - /// { - /// Flavor = SelfExtractorFlavor.WinFormsApplication, - /// DefaultExtractDirectory = "%USERPROFILE%\\ExtractHere", - /// PostExtractCommandLine = ExeToRunAfterExtract, - /// SfxExeWindowTitle = "My Custom Window Title", - /// RemoveUnpackedFilesAfterExecute = true - /// }; - /// zip.SaveSelfExtractor("archive.exe", options); - /// } - /// - /// - /// Dim DirectoryPath As String = "c:\Documents\Project7" - /// Using zip As New ZipFile() - /// zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)) - /// zip.Comment = "This will be embedded into a self-extracting console-based exe" - /// Dim options As New SelfExtractorOptions() - /// options.Flavor = SelfExtractorFlavor.WinFormsApplication - /// options.DefaultExtractDirectory = "%USERPROFILE%\\ExtractHere" - /// options.PostExtractCommandLine = ExeToRunAfterExtract - /// options.SfxExeWindowTitle = "My Custom Window Title" - /// options.RemoveUnpackedFilesAfterExecute = True - /// zip.SaveSelfExtractor("archive.exe", options) - /// End Using - /// - /// - /// - /// The name of the EXE to generate. - /// provides the options for creating the - /// Self-extracting archive. - public void SaveSelfExtractor(string exeToGenerate, SelfExtractorSaveOptions options) - { - // Save an SFX that is both an EXE and a ZIP. - - // Check for the case where we are re-saving a zip archive - // that was originally instantiated with a stream. In that case, - // the _name will be null. If so, we set _writestream to null, - // which insures that we'll cons up a new WriteStream (with a filesystem - // file backing it) in the Save() method. - if (_name == null) - _writestream = null; - - _SavingSfx = true; - _name = exeToGenerate; - if (Directory.Exists(_name)) - throw new ZipException("Bad Directory", new System.ArgumentException("That name specifies an existing directory. Please specify a filename.", "exeToGenerate")); - _contentsChanged = true; - _fileAlreadyExists = File.Exists(_name); - - _SaveSfxStub(exeToGenerate, options); - - Save(); - _SavingSfx = false; - } - - - - - private static void ExtractResourceToFile(Assembly a, string resourceName, string filename) - { - int n = 0; - byte[] bytes = new byte[1024]; - using (Stream instream = a.GetManifestResourceStream(resourceName)) - { - if (instream == null) - throw new ZipException(String.Format("missing resource '{0}'", resourceName)); - - using (FileStream outstream = File.OpenWrite(filename)) - { - do - { - n = instream.Read(bytes, 0, bytes.Length); - outstream.Write(bytes, 0, n); - } while (n > 0); - } - } - } - - - private void _SaveSfxStub(string exeToGenerate, SelfExtractorSaveOptions options) - { - string nameOfIconFile = null; - string stubExe = null; - string unpackedResourceDir = null; - string tmpDir = null; - try - { - if (File.Exists(exeToGenerate)) - { - if (Verbose) StatusMessageTextWriter.WriteLine("The existing file ({0}) will be overwritten.", exeToGenerate); - } - if (!exeToGenerate.EndsWith(".exe")) - { - if (Verbose) StatusMessageTextWriter.WriteLine("Warning: The generated self-extracting file will not have an .exe extension."); - } - - // workitem 10553 - tmpDir = TempFileFolder ?? Path.GetDirectoryName(exeToGenerate); - stubExe = GenerateTempPathname(tmpDir, "exe"); - - // get the Ionic.Zip assembly - Assembly a1 = typeof(ZipFile).Assembly; - - using (var csharp = new Microsoft.CSharp.CSharpCodeProvider - (new Dictionary() { { "CompilerVersion", "v2.0" } })) { - - // The following is a perfect opportunity for a linq query, but - // I cannot use it. DotNetZip needs to run on .NET 2.0, - // and using LINQ would break that. Here's what it would look - // like: - // - // var settings = (from x in SettingsList - // where x.Flavor == flavor - // select x).First(); - - ExtractorSettings settings = null; - foreach (var x in SettingsList) - { - if (x.Flavor == options.Flavor) - { - settings = x; - break; - } - } - - // sanity check; should never happen - if (settings == null) - throw new BadStateException(String.Format("While saving a Self-Extracting Zip, Cannot find that flavor ({0})?", options.Flavor)); - - // This is the list of referenced assemblies. Ionic.Zip is - // needed here. Also if it is the winforms (gui) extractor, we - // need other referenced assemblies, like - // System.Windows.Forms.dll, etc. - var cp = new System.CodeDom.Compiler.CompilerParameters(); - cp.ReferencedAssemblies.Add(a1.Location); - if (settings.ReferencedAssemblies != null) - foreach (string ra in settings.ReferencedAssemblies) - cp.ReferencedAssemblies.Add(ra); - - cp.GenerateInMemory = false; - cp.GenerateExecutable = true; - cp.IncludeDebugInformation = false; - cp.CompilerOptions = ""; - - Assembly a2 = Assembly.GetExecutingAssembly(); - - // Use this to concatenate all the source code resources into a - // single module. - var sb = new System.Text.StringBuilder(); - - // In case there are compiler errors later, we allocate a source - // file name now. If errors are detected, we'll spool the source - // code as well as the errors (in comments) into that filename, - // and throw an exception with the filename. Makes it easier to - // diagnose. This should be rare; most errors happen only - // during devlpmt of DotNetZip itself, but there are rare - // occasions when they occur in other cases. - string sourceFile = GenerateTempPathname(tmpDir, "cs"); - - - // // debugging: enumerate the resources in this assembly - // Console.WriteLine("Resources in this assembly:"); - // foreach (string rsrc in a2.GetManifestResourceNames()) - // { - // Console.WriteLine(rsrc); - // } - // Console.WriteLine(); - - - // all the source code is embedded in the DLL as a zip file. - using (ZipFile zip = ZipFile.Read(a2.GetManifestResourceStream("Ionic.Zip.Resources.ZippedResources.zip"))) - { - // // debugging: enumerate the files in the embedded zip - // Console.WriteLine("Entries in the embbedded zip:"); - // foreach (ZipEntry entry in zip) - // { - // Console.WriteLine(entry.FileName); - // } - // Console.WriteLine(); - - unpackedResourceDir = GenerateTempPathname(tmpDir, "tmp"); - - if (String.IsNullOrEmpty(options.IconFile)) - { - // Use the ico file that is embedded into the Ionic.Zip - // DLL itself. To do this we must unpack the icon to - // the filesystem, in order to specify it on the cmdline - // of csc.exe. This method will remove the unpacked - // file later. - System.IO.Directory.CreateDirectory(unpackedResourceDir); - ZipEntry e = zip["zippedFile.ico"]; - // Must not extract a readonly file - it will be impossible to - // delete later. - if ((e.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly) - e.Attributes ^= FileAttributes.ReadOnly; - e.Extract(unpackedResourceDir); - nameOfIconFile = Path.Combine(unpackedResourceDir, "zippedFile.ico"); - cp.CompilerOptions += String.Format("/win32icon:\"{0}\"", nameOfIconFile); - } - else - cp.CompilerOptions += String.Format("/win32icon:\"{0}\"", options.IconFile); - - cp.OutputAssembly = stubExe; - - if (options.Flavor == SelfExtractorFlavor.WinFormsApplication) - cp.CompilerOptions += " /target:winexe"; - - if (!String.IsNullOrEmpty(options.AdditionalCompilerSwitches)) - cp.CompilerOptions += " " + options.AdditionalCompilerSwitches; - - if (String.IsNullOrEmpty(cp.CompilerOptions)) - cp.CompilerOptions = null; - - if ((settings.CopyThroughResources != null) && (settings.CopyThroughResources.Count != 0)) - { - if (!Directory.Exists(unpackedResourceDir)) System.IO.Directory.CreateDirectory(unpackedResourceDir); - foreach (string re in settings.CopyThroughResources) - { - string filename = Path.Combine(unpackedResourceDir, re); - - ExtractResourceToFile(a2, re, filename); - // add the file into the target assembly as an embedded resource - cp.EmbeddedResources.Add(filename); - } - } - - // add the Ionic.Utils.Zip DLL as an embedded resource - cp.EmbeddedResources.Add(a1.Location); - - // file header - sb.Append("// " + Path.GetFileName(sourceFile) + "\n") - .Append("// --------------------------------------------\n//\n") - .Append("// This SFX source file was generated by DotNetZip ") - .Append(ZipFile.LibraryVersion.ToString()) - .Append("\n// at ") - .Append(System.DateTime.Now.ToString("yyyy MMMM dd HH:mm:ss")) - .Append("\n//\n// --------------------------------------------\n\n\n"); - - // assembly attributes - if (!String.IsNullOrEmpty(options.Description)) - sb.Append("[assembly: System.Reflection.AssemblyTitle(\"" - + options.Description.Replace("\"", "") - + "\")]\n"); - else - sb.Append("[assembly: System.Reflection.AssemblyTitle(\"DotNetZip SFX Archive\")]\n"); - - if (!String.IsNullOrEmpty(options.ProductVersion)) - sb.Append("[assembly: System.Reflection.AssemblyInformationalVersion(\"" - + options.ProductVersion.Replace("\"", "") - + "\")]\n"); - - // workitem - string copyright = - (String.IsNullOrEmpty(options.Copyright)) - ? "Extractor: Copyright © Dino Chiesa 2008-2011" - : options.Copyright.Replace("\"", ""); - - if (!String.IsNullOrEmpty(options.ProductName)) - sb.Append("[assembly: System.Reflection.AssemblyProduct(\"") - .Append(options.ProductName.Replace("\"", "")) - .Append("\")]\n"); - else - sb.Append("[assembly: System.Reflection.AssemblyProduct(\"DotNetZip\")]\n"); - - - sb.Append("[assembly: System.Reflection.AssemblyCopyright(\"" + copyright + "\")]\n") - .Append(String.Format("[assembly: System.Reflection.AssemblyVersion(\"{0}\")]\n", ZipFile.LibraryVersion.ToString())); - if (options.FileVersion != null) - sb.Append(String.Format("[assembly: System.Reflection.AssemblyFileVersion(\"{0}\")]\n", - options.FileVersion.ToString())); - - sb.Append("\n\n\n"); - - // Set the default extract location if it is available - string extractLoc = options.DefaultExtractDirectory; - if (extractLoc != null) - { - // remove double-quotes and replace slash with double-slash. - // This, because the value is going to be embedded into a - // cs file as a quoted string, and it needs to be escaped. - extractLoc = extractLoc.Replace("\"", "").Replace("\\", "\\\\"); - } - - string postExCmdLine = options.PostExtractCommandLine; - if (postExCmdLine != null) - { - postExCmdLine = postExCmdLine.Replace("\\", "\\\\"); - postExCmdLine = postExCmdLine.Replace("\"", "\\\""); - } - - - foreach (string rc in settings.ResourcesToCompile) - { - using (Stream s = zip[rc].OpenReader()) - { - if (s == null) - throw new ZipException(String.Format("missing resource '{0}'", rc)); - using (StreamReader sr = new StreamReader(s)) - { - while (sr.Peek() >= 0) - { - string line = sr.ReadLine(); - if (extractLoc != null) - line = line.Replace("@@EXTRACTLOCATION", extractLoc); - - line = line.Replace("@@REMOVE_AFTER_EXECUTE", options.RemoveUnpackedFilesAfterExecute.ToString()); - line = line.Replace("@@QUIET", options.Quiet.ToString()); - if (!String.IsNullOrEmpty(options.SfxExeWindowTitle)) - - line = line.Replace("@@SFX_EXE_WINDOW_TITLE", options.SfxExeWindowTitle); - - line = line.Replace("@@EXTRACT_EXISTING_FILE", ((int)options.ExtractExistingFile).ToString()); - - if (postExCmdLine != null) - line = line.Replace("@@POST_UNPACK_CMD_LINE", postExCmdLine); - - sb.Append(line).Append("\n"); - } - } - sb.Append("\n\n"); - } - } - } - - string LiteralSource = sb.ToString(); - -#if DEBUGSFX - // for debugging only - string sourceModule = GenerateTempPathname(tmpDir, "cs"); - using (StreamWriter sw = File.CreateText(sourceModule)) - { - sw.Write(LiteralSource); - } - Console.WriteLine("source: {0}", sourceModule); -#endif - - var cr = csharp.CompileAssemblyFromSource(cp, LiteralSource); - - - if (cr == null) - throw new SfxGenerationException("Cannot compile the extraction logic!"); - - if (Verbose) - foreach (string output in cr.Output) - StatusMessageTextWriter.WriteLine(output); - - if (cr.Errors.Count != 0) - { - using (TextWriter tw = new StreamWriter(sourceFile)) - { - // first, the source we compiled - tw.Write(LiteralSource); - - // now, append the compile errors - tw.Write("\n\n\n// ------------------------------------------------------------------\n"); - tw.Write("// Errors during compilation: \n//\n"); - string p = Path.GetFileName(sourceFile); - - foreach (System.CodeDom.Compiler.CompilerError error in cr.Errors) - { - tw.Write(String.Format("// {0}({1},{2}): {3} {4}: {5}\n//\n", - p, // 0 - error.Line, // 1 - error.Column, // 2 - error.IsWarning ? "Warning" : "error", // 3 - error.ErrorNumber, // 4 - error.ErrorText)); // 5 - } - } - throw new SfxGenerationException(String.Format("Errors compiling the extraction logic! {0}", sourceFile)); - } - - OnSaveEvent(ZipProgressEventType.Saving_AfterCompileSelfExtractor); - - // Now, copy the resulting EXE image to the _writestream. - // Because this stub exe is being saved first, the effect will be to - // concatenate the exe and the zip data together. - using (System.IO.Stream input = System.IO.File.OpenRead(stubExe)) - { - byte[] buffer = new byte[4000]; - int n = 1; - while (n != 0) - { - n = input.Read(buffer, 0, buffer.Length); - if (n != 0) - WriteStream.Write(buffer, 0, n); - } - } - } - - OnSaveEvent(ZipProgressEventType.Saving_AfterSaveTempArchive); - } - finally - { - try - { - if (Directory.Exists(unpackedResourceDir)) - { - try { Directory.Delete(unpackedResourceDir, true); } - catch (System.IO.IOException exc1) - { - StatusMessageTextWriter.WriteLine("Warning: Exception: {0}", exc1); - } - } - if (File.Exists(stubExe)) - { - try { File.Delete(stubExe); } - catch (System.IO.IOException exc1) - { - StatusMessageTextWriter.WriteLine("Warning: Exception: {0}", exc1); - } - } - } - catch (System.IO.IOException) { } - } - - return; - - } - - - - internal static string GenerateTempPathname(string dir, string extension) - { - string candidate = null; - String AppName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name; - do - { - // workitem 13475 - string uuid = System.Guid.NewGuid().ToString(); - - string Name = String.Format("{0}-{1}-{2}.{3}", - AppName, System.DateTime.Now.ToString("yyyyMMMdd-HHmmss"), - uuid, extension); - candidate = System.IO.Path.Combine(dir, Name); - } while (System.IO.File.Exists(candidate) || System.IO.Directory.Exists(candidate)); - - // The candidate path does not exist as a file or directory. - // It can now be created, as a file or directory. - return candidate; - } - - } -#endif -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Selector.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Selector.cs deleted file mode 100644 index 31c3fd82..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.Selector.cs +++ /dev/null @@ -1,1464 +0,0 @@ -// ZipFile.Selector.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2009-2010 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-August-06 09:35:58> -// -// ------------------------------------------------------------------ -// -// This module defines methods in the ZipFile class associated to the FileFilter -// capability - selecting files to add into the archive, or selecting entries to -// retrieve from the archive based on criteria including the filename, size, date, or -// attributes. It is something like a "poor man's LINQ". I included it into DotNetZip -// because not everyone has .NET 3.5 yet. When using DotNetZip on .NET 3.5, the LINQ -// query/selection will be superior. -// -// These methods are segregated into a different module to facilitate easy exclusion for -// those people who wish to have a smaller library without this function. -// -// ------------------------------------------------------------------ - - -using System; -using System.IO; -using System.Collections.Generic; - -namespace Ionic.Zip -{ - - partial class ZipFile - { - /// - /// Adds to the ZipFile a set of files from the current working directory on - /// disk, that conform to the specified criteria. - /// - /// - /// - /// - /// This method selects files from the the current working directory matching - /// the specified criteria, and adds them to the ZipFile. - /// - /// - /// - /// Specify the criteria in statements of 3 elements: a noun, an operator, and - /// a value. Consider the string "name != *.doc" . The noun is "name". The - /// operator is "!=", implying "Not Equal". The value is "*.doc". That - /// criterion, in English, says "all files with a name that does not end in - /// the .doc extension." - /// - /// - /// - /// Supported nouns include "name" (or "filename") for the filename; "atime", - /// "mtime", and "ctime" for last access time, last modfied time, and created - /// time of the file, respectively; "attributes" (or "attrs") for the file - /// attributes; "size" (or "length") for the file length (uncompressed), and - /// "type" for the type of object, either a file or a directory. The - /// "attributes", "name" and "type" nouns both support = and != as operators. - /// The "size", "atime", "mtime", and "ctime" nouns support = and !=, and - /// >, >=, <, <= as well. The times are taken to be expressed in - /// local time. - /// - /// - /// - /// Specify values for the file attributes as a string with one or more of the - /// characters H,R,S,A,I,L in any order, implying file attributes of Hidden, - /// ReadOnly, System, Archive, NotContextIndexed, and ReparsePoint (symbolic - /// link) respectively. - /// - /// - /// - /// To specify a time, use YYYY-MM-DD-HH:mm:ss or YYYY/MM/DD-HH:mm:ss as the - /// format. If you omit the HH:mm:ss portion, it is assumed to be 00:00:00 - /// (midnight). - /// - /// - /// - /// The value for a size criterion is expressed in integer quantities of bytes, - /// kilobytes (use k or kb after the number), megabytes (m or mb), or gigabytes - /// (g or gb). - /// - /// - /// - /// The value for a name is a pattern to match against the filename, potentially - /// including wildcards. The pattern follows CMD.exe glob rules: * implies one - /// or more of any character, while ? implies one character. If the name - /// pattern contains any slashes, it is matched to the entire filename, - /// including the path; otherwise, it is matched against only the filename - /// without the path. This means a pattern of "*\*.*" matches all files one - /// directory level deep, while a pattern of "*.*" matches all files in all - /// directories. - /// - /// - /// - /// To specify a name pattern that includes spaces, use single quotes around the - /// pattern. A pattern of "'* *.*'" will match all files that have spaces in - /// the filename. The full criteria string for that would be "name = '* *.*'" . - /// - /// - /// - /// The value for a type criterion is either F (implying a file) or D (implying - /// a directory). - /// - /// - /// - /// Some examples: - /// - /// - /// - /// - /// criteria - /// Files retrieved - /// - /// - /// - /// name != *.xls - /// any file with an extension that is not .xls - /// - /// - /// - /// - /// name = *.mp3 - /// any file with a .mp3 extension. - /// - /// - /// - /// - /// *.mp3 - /// (same as above) any file with a .mp3 extension. - /// - /// - /// - /// - /// attributes = A - /// all files whose attributes include the Archive bit. - /// - /// - /// - /// - /// attributes != H - /// all files whose attributes do not include the Hidden bit. - /// - /// - /// - /// - /// mtime > 2009-01-01 - /// all files with a last modified time after January 1st, 2009. - /// - /// - /// - /// - /// size > 2gb - /// all files whose uncompressed size is greater than 2gb. - /// - /// - /// - /// - /// type = D - /// all directories in the filesystem. - /// - /// - /// - /// - /// - /// You can combine criteria with the conjunctions AND or OR. Using a string - /// like "name = *.txt AND size >= 100k" for the selectionCriteria retrieves - /// entries whose names end in .txt, and whose uncompressed size is greater than - /// or equal to 100 kilobytes. - /// - /// - /// - /// For more complex combinations of criteria, you can use parenthesis to group - /// clauses in the boolean logic. Without parenthesis, the precedence of the - /// criterion atoms is determined by order of appearance. Unlike the C# - /// language, the AND conjunction does not take precendence over the logical OR. - /// This is important only in strings that contain 3 or more criterion atoms. - /// In other words, "name = *.txt and size > 1000 or attributes = H" implies - /// "((name = *.txt AND size > 1000) OR attributes = H)" while "attributes = - /// H OR name = *.txt and size > 1000" evaluates to "((attributes = H OR name - /// = *.txt) AND size > 1000)". When in doubt, use parenthesis. - /// - /// - /// - /// Using time properties requires some extra care. If you want to retrieve all - /// entries that were last updated on 2009 February 14, specify a time range - /// like so:"mtime >= 2009-02-14 AND mtime < 2009-02-15". Read this to - /// say: all files updated after 12:00am on February 14th, until 12:00am on - /// February 15th. You can use the same bracketing approach to specify any time - /// period - a year, a month, a week, and so on. - /// - /// - /// - /// The syntax allows one special case: if you provide a string with no spaces, it is - /// treated as a pattern to match for the filename. Therefore a string like "*.xls" - /// will be equivalent to specifying "name = *.xls". - /// - /// - /// - /// There is no logic in this method that insures that the file inclusion - /// criteria are internally consistent. For example, it's possible to specify - /// criteria that says the file must have a size of less than 100 bytes, as well - /// as a size that is greater than 1000 bytes. Obviously no file will ever - /// satisfy such criteria, but this method does not detect such logical - /// inconsistencies. The caller is responsible for insuring the criteria are - /// sensible. - /// - /// - /// - /// Using this method, the file selection does not recurse into - /// subdirectories, and the full path of the selected files is included in the - /// entries added into the zip archive. If you don't like these behaviors, - /// see the other overloads of this method. - /// - /// - /// - /// - /// This example zips up all *.csv files in the current working directory. - /// - /// using (ZipFile zip = new ZipFile()) - /// { - /// // To just match on filename wildcards, - /// // use the shorthand form of the selectionCriteria string. - /// zip.AddSelectedFiles("*.csv"); - /// zip.Save(PathToZipArchive); - /// } - /// - /// - /// Using zip As ZipFile = New ZipFile() - /// zip.AddSelectedFiles("*.csv") - /// zip.Save(PathToZipArchive) - /// End Using - /// - /// - /// - /// The criteria for file selection - public void AddSelectedFiles(String selectionCriteria) - { - this.AddSelectedFiles(selectionCriteria, ".", null, false); - } - - /// - /// Adds to the ZipFile a set of files from the disk that conform to the - /// specified criteria, optionally recursing into subdirectories. - /// - /// - /// - /// - /// This method selects files from the the current working directory matching - /// the specified criteria, and adds them to the ZipFile. If - /// recurseDirectories is true, files are also selected from - /// subdirectories, and the directory structure in the filesystem is - /// reproduced in the zip archive, rooted at the current working directory. - /// - /// - /// - /// Using this method, the full path of the selected files is included in the - /// entries added into the zip archive. If you don't want this behavior, use - /// one of the overloads of this method that allows the specification of a - /// directoryInArchive. - /// - /// - /// - /// For details on the syntax for the selectionCriteria parameter, see . - /// - /// - /// - /// - /// - /// - /// This example zips up all *.xml files in the current working directory, or any - /// subdirectory, that are larger than 1mb. - /// - /// - /// using (ZipFile zip = new ZipFile()) - /// { - /// // Use a compound expression in the selectionCriteria string. - /// zip.AddSelectedFiles("name = *.xml and size > 1024kb", true); - /// zip.Save(PathToZipArchive); - /// } - /// - /// - /// Using zip As ZipFile = New ZipFile() - /// ' Use a compound expression in the selectionCriteria string. - /// zip.AddSelectedFiles("name = *.xml and size > 1024kb", true) - /// zip.Save(PathToZipArchive) - /// End Using - /// - /// - /// - /// The criteria for file selection - /// - /// - /// If true, the file selection will recurse into subdirectories. - /// - public void AddSelectedFiles(String selectionCriteria, bool recurseDirectories) - { - this.AddSelectedFiles(selectionCriteria, ".", null, recurseDirectories); - } - - /// - /// Adds to the ZipFile a set of files from a specified directory in the - /// filesystem, that conform to the specified criteria. - /// - /// - /// - /// - /// This method selects files that conform to the specified criteria, from the - /// the specified directory on disk, and adds them to the ZipFile. The search - /// does not recurse into subdirectores. - /// - /// - /// - /// Using this method, the full filesystem path of the files on disk is - /// reproduced on the entries added to the zip file. If you don't want this - /// behavior, use one of the other overloads of this method. - /// - /// - /// - /// For details on the syntax for the selectionCriteria parameter, see . - /// - /// - /// - /// - /// - /// - /// This example zips up all *.xml files larger than 1mb in the directory - /// given by "d:\rawdata". - /// - /// - /// using (ZipFile zip = new ZipFile()) - /// { - /// // Use a compound expression in the selectionCriteria string. - /// zip.AddSelectedFiles("name = *.xml and size > 1024kb", "d:\\rawdata"); - /// zip.Save(PathToZipArchive); - /// } - /// - /// - /// - /// Using zip As ZipFile = New ZipFile() - /// ' Use a compound expression in the selectionCriteria string. - /// zip.AddSelectedFiles("name = *.xml and size > 1024kb", "d:\rawdata) - /// zip.Save(PathToZipArchive) - /// End Using - /// - /// - /// - /// The criteria for file selection - /// - /// - /// The name of the directory on the disk from which to select files. - /// - public void AddSelectedFiles(String selectionCriteria, String directoryOnDisk) - { - this.AddSelectedFiles(selectionCriteria, directoryOnDisk, null, false); - } - - - /// - /// Adds to the ZipFile a set of files from the specified directory on disk, - /// that conform to the specified criteria. - /// - /// - /// - /// - /// - /// This method selects files from the the specified disk directory matching - /// the specified selection criteria, and adds them to the ZipFile. If - /// recurseDirectories is true, files are also selected from - /// subdirectories. - /// - /// - /// - /// The full directory structure in the filesystem is reproduced on the - /// entries added to the zip archive. If you don't want this behavior, use - /// one of the overloads of this method that allows the specification of a - /// directoryInArchive. - /// - /// - /// - /// For details on the syntax for the selectionCriteria parameter, see . - /// - /// - /// - /// - /// - /// This example zips up all *.csv files in the "files" directory, or any - /// subdirectory, that have been saved since 2009 February 14th. - /// - /// - /// using (ZipFile zip = new ZipFile()) - /// { - /// // Use a compound expression in the selectionCriteria string. - /// zip.AddSelectedFiles("name = *.csv and mtime > 2009-02-14", "files", true); - /// zip.Save(PathToZipArchive); - /// } - /// - /// - /// Using zip As ZipFile = New ZipFile() - /// ' Use a compound expression in the selectionCriteria string. - /// zip.AddSelectedFiles("name = *.csv and mtime > 2009-02-14", "files", true) - /// zip.Save(PathToZipArchive) - /// End Using - /// - /// - /// - /// - /// This example zips up all files in the current working - /// directory, and all its child directories, except those in - /// the excludethis subdirectory. - /// - /// Using Zip As ZipFile = New ZipFile(zipfile) - /// Zip.AddSelectedFfiles("name != 'excludethis\*.*'", datapath, True) - /// Zip.Save() - /// End Using - /// - /// - /// - /// The criteria for file selection - /// - /// - /// The filesystem path from which to select files. - /// - /// - /// - /// If true, the file selection will recurse into subdirectories. - /// - public void AddSelectedFiles(String selectionCriteria, String directoryOnDisk, bool recurseDirectories) - { - this.AddSelectedFiles(selectionCriteria, directoryOnDisk, null, recurseDirectories); - } - - - /// - /// Adds to the ZipFile a selection of files from the specified directory on - /// disk, that conform to the specified criteria, and using a specified root - /// path for entries added to the zip archive. - /// - /// - /// - /// - /// This method selects files from the specified disk directory matching the - /// specified selection criteria, and adds those files to the ZipFile, using - /// the specified directory path in the archive. The search does not recurse - /// into subdirectories. For details on the syntax for the selectionCriteria - /// parameter, see . - /// - /// - /// - /// - /// - /// - /// This example zips up all *.psd files in the "photos" directory that have - /// been saved since 2009 February 14th, and puts them all in a zip file, - /// using the directory name of "content" in the zip archive itself. When the - /// zip archive is unzipped, the folder containing the .psd files will be - /// named "content". - /// - /// - /// using (ZipFile zip = new ZipFile()) - /// { - /// // Use a compound expression in the selectionCriteria string. - /// zip.AddSelectedFiles("name = *.psd and mtime > 2009-02-14", "photos", "content"); - /// zip.Save(PathToZipArchive); - /// } - /// - /// - /// Using zip As ZipFile = New ZipFile - /// zip.AddSelectedFiles("name = *.psd and mtime > 2009-02-14", "photos", "content") - /// zip.Save(PathToZipArchive) - /// End Using - /// - /// - /// - /// - /// The criteria for selection of files to add to the ZipFile. - /// - /// - /// - /// The path to the directory in the filesystem from which to select files. - /// - /// - /// - /// Specifies a directory path to use to in place of the - /// directoryOnDisk. This path may, or may not, correspond to a real - /// directory in the current filesystem. If the files within the zip are - /// later extracted, this is the path used for the extracted file. Passing - /// null (nothing in VB) will use the path on the file name, if any; in other - /// words it would use directoryOnDisk, plus any subdirectory. Passing - /// the empty string ("") will insert the item at the root path within the - /// archive. - /// - public void AddSelectedFiles(String selectionCriteria, - String directoryOnDisk, - String directoryPathInArchive) - { - this.AddSelectedFiles(selectionCriteria, directoryOnDisk, directoryPathInArchive, false); - } - - /// - /// Adds to the ZipFile a selection of files from the specified directory on - /// disk, that conform to the specified criteria, optionally recursing through - /// subdirectories, and using a specified root path for entries added to the - /// zip archive. - /// - /// - /// - /// This method selects files from the specified disk directory that match the - /// specified selection criteria, and adds those files to the ZipFile, using - /// the specified directory path in the archive. If recurseDirectories - /// is true, files are also selected from subdirectories, and the directory - /// structure in the filesystem is reproduced in the zip archive, rooted at - /// the directory specified by directoryOnDisk. For details on the - /// syntax for the selectionCriteria parameter, see . - /// - /// - /// - /// - /// This example zips up all files that are NOT *.pst files, in the current - /// working directory and any subdirectories. - /// - /// - /// using (ZipFile zip = new ZipFile()) - /// { - /// zip.AddSelectedFiles("name != *.pst", SourceDirectory, "backup", true); - /// zip.Save(PathToZipArchive); - /// } - /// - /// - /// Using zip As ZipFile = New ZipFile - /// zip.AddSelectedFiles("name != *.pst", SourceDirectory, "backup", true) - /// zip.Save(PathToZipArchive) - /// End Using - /// - /// - /// - /// - /// The criteria for selection of files to add to the ZipFile. - /// - /// - /// - /// The path to the directory in the filesystem from which to select files. - /// - /// - /// - /// Specifies a directory path to use to in place of the - /// directoryOnDisk. This path may, or may not, correspond to a real - /// directory in the current filesystem. If the files within the zip are - /// later extracted, this is the path used for the extracted file. Passing - /// null (nothing in VB) will use the path on the file name, if any; in other - /// words it would use directoryOnDisk, plus any subdirectory. Passing - /// the empty string ("") will insert the item at the root path within the - /// archive. - /// - /// - /// - /// If true, the method also scans subdirectories for files matching the - /// criteria. - /// - public void AddSelectedFiles(String selectionCriteria, - String directoryOnDisk, - String directoryPathInArchive, - bool recurseDirectories) - { - _AddOrUpdateSelectedFiles(selectionCriteria, - directoryOnDisk, - directoryPathInArchive, - recurseDirectories, - false); - } - - /// - /// Updates the ZipFile with a selection of files from the disk that conform - /// to the specified criteria. - /// - /// - /// - /// This method selects files from the specified disk directory that match the - /// specified selection criteria, and Updates the ZipFile with those - /// files, using the specified directory path in the archive. If - /// recurseDirectories is true, files are also selected from - /// subdirectories, and the directory structure in the filesystem is - /// reproduced in the zip archive, rooted at the directory specified by - /// directoryOnDisk. For details on the syntax for the - /// selectionCriteria parameter, see . - /// - /// - /// - /// The criteria for selection of files to add to the ZipFile. - /// - /// - /// - /// The path to the directory in the filesystem from which to select files. - /// - /// - /// - /// Specifies a directory path to use to in place of the - /// directoryOnDisk. This path may, or may not, correspond to a - /// real directory in the current filesystem. If the files within the zip - /// are later extracted, this is the path used for the extracted file. - /// Passing null (nothing in VB) will use the path on the file name, if - /// any; in other words it would use directoryOnDisk, plus any - /// subdirectory. Passing the empty string ("") will insert the item at - /// the root path within the archive. - /// - /// - /// - /// If true, the method also scans subdirectories for files matching the criteria. - /// - /// - /// - public void UpdateSelectedFiles(String selectionCriteria, - String directoryOnDisk, - String directoryPathInArchive, - bool recurseDirectories) - { - _AddOrUpdateSelectedFiles(selectionCriteria, - directoryOnDisk, - directoryPathInArchive, - recurseDirectories, - true); - } - - - private string EnsureendInSlash(string s) - { - if (s.EndsWith("\\")) return s; - return s + "\\"; - } - - private void _AddOrUpdateSelectedFiles(String selectionCriteria, - String directoryOnDisk, - String directoryPathInArchive, - bool recurseDirectories, - bool wantUpdate) - { - if (directoryOnDisk == null && (Directory.Exists(selectionCriteria))) - { - directoryOnDisk = selectionCriteria; - selectionCriteria = "*.*"; - } - else if (String.IsNullOrEmpty(directoryOnDisk)) - { - directoryOnDisk = "."; - } - - // workitem 9176 - while (directoryOnDisk.EndsWith("\\")) directoryOnDisk = directoryOnDisk.Substring(0, directoryOnDisk.Length - 1); - if (Verbose) StatusMessageTextWriter.WriteLine("adding selection '{0}' from dir '{1}'...", - selectionCriteria, directoryOnDisk); - Ionic.FileSelector ff = new Ionic.FileSelector(selectionCriteria, - AddDirectoryWillTraverseReparsePoints); - var itemsToAdd = ff.SelectFiles(directoryOnDisk, recurseDirectories); - - if (Verbose) StatusMessageTextWriter.WriteLine("found {0} files...", itemsToAdd.Count); - - OnAddStarted(); - - AddOrUpdateAction action = (wantUpdate) ? AddOrUpdateAction.AddOrUpdate : AddOrUpdateAction.AddOnly; - foreach (var item in itemsToAdd) - { - // workitem 10153 - string dirInArchive = (directoryPathInArchive == null) - ? null - // workitem 12260 - : ReplaceLeadingDirectory(Path.GetDirectoryName(item), - directoryOnDisk, - directoryPathInArchive); - - if (File.Exists(item)) - { - if (wantUpdate) - this.UpdateFile(item, dirInArchive); - else - this.AddFile(item, dirInArchive); - } - else - { - // this adds "just" the directory, without recursing to the contained files - AddOrUpdateDirectoryImpl(item, dirInArchive, action, false, 0); - } - } - - OnAddCompleted(); - } - - - // workitem 12260 - private static string ReplaceLeadingDirectory(string original, - string pattern, - string replacement) - { - string upperString = original.ToUpper(); - string upperPattern = pattern.ToUpper(); - int p1 = upperString.IndexOf(upperPattern); - if (p1 != 0) return original; - return replacement + original.Substring(upperPattern.Length); - } - -#if NOT - private static string ReplaceEx(string original, - string pattern, - string replacement) - { - int count, position0, position1; - count = position0 = position1 = 0; - string upperString = original.ToUpper(); - string upperPattern = pattern.ToUpper(); - int inc = (original.Length/pattern.Length) * - (replacement.Length-pattern.Length); - char [] chars = new char[original.Length + Math.Max(0, inc)]; - while( (position1 = upperString.IndexOf(upperPattern, - position0)) != -1 ) - { - for ( int i=position0 ; i < position1 ; ++i ) - chars[count++] = original[i]; - for ( int i=0 ; i < replacement.Length ; ++i ) - chars[count++] = replacement[i]; - position0 = position1+pattern.Length; - } - if ( position0 == 0 ) return original; - for ( int i=position0 ; i < original.Length ; ++i ) - chars[count++] = original[i]; - return new string(chars, 0, count); - } -#endif - - /// - /// Retrieve entries from the zipfile by specified criteria. - /// - /// - /// - /// - /// This method allows callers to retrieve the collection of entries from the zipfile - /// that fit the specified criteria. The criteria are described in a string format, and - /// can include patterns for the filename; constraints on the size of the entry; - /// constraints on the last modified, created, or last accessed time for the file - /// described by the entry; or the attributes of the entry. - /// - /// - /// - /// For details on the syntax for the selectionCriteria parameter, see . - /// - /// - /// - /// This method is intended for use with a ZipFile that has been read from storage. - /// When creating a new ZipFile, this method will work only after the ZipArchive has - /// been Saved to the disk (the ZipFile class subsequently and implicitly reads the Zip - /// archive from storage.) Calling SelectEntries on a ZipFile that has not yet been - /// saved will deliver undefined results. - /// - /// - /// - /// - /// Thrown if selectionCriteria has an invalid syntax. - /// - /// - /// - /// This example selects all the PhotoShop files from within an archive, and extracts them - /// to the current working directory. - /// - /// using (ZipFile zip1 = ZipFile.Read(ZipFileName)) - /// { - /// var PhotoShopFiles = zip1.SelectEntries("*.psd"); - /// foreach (ZipEntry psd in PhotoShopFiles) - /// { - /// psd.Extract(); - /// } - /// } - /// - /// - /// Using zip1 As ZipFile = ZipFile.Read(ZipFileName) - /// Dim PhotoShopFiles as ICollection(Of ZipEntry) - /// PhotoShopFiles = zip1.SelectEntries("*.psd") - /// Dim psd As ZipEntry - /// For Each psd In PhotoShopFiles - /// psd.Extract - /// Next - /// End Using - /// - /// - /// the string that specifies which entries to select - /// a collection of ZipEntry objects that conform to the inclusion spec - public ICollection SelectEntries(String selectionCriteria) - { - Ionic.FileSelector ff = new Ionic.FileSelector(selectionCriteria, - AddDirectoryWillTraverseReparsePoints); - return ff.SelectEntries(this); - } - - - /// - /// Retrieve entries from the zipfile by specified criteria. - /// - /// - /// - /// - /// This method allows callers to retrieve the collection of entries from the zipfile - /// that fit the specified criteria. The criteria are described in a string format, and - /// can include patterns for the filename; constraints on the size of the entry; - /// constraints on the last modified, created, or last accessed time for the file - /// described by the entry; or the attributes of the entry. - /// - /// - /// - /// For details on the syntax for the selectionCriteria parameter, see . - /// - /// - /// - /// This method is intended for use with a ZipFile that has been read from storage. - /// When creating a new ZipFile, this method will work only after the ZipArchive has - /// been Saved to the disk (the ZipFile class subsequently and implicitly reads the Zip - /// archive from storage.) Calling SelectEntries on a ZipFile that has not yet been - /// saved will deliver undefined results. - /// - /// - /// - /// - /// Thrown if selectionCriteria has an invalid syntax. - /// - /// - /// - /// - /// using (ZipFile zip1 = ZipFile.Read(ZipFileName)) - /// { - /// var UpdatedPhotoShopFiles = zip1.SelectEntries("*.psd", "UpdatedFiles"); - /// foreach (ZipEntry e in UpdatedPhotoShopFiles) - /// { - /// // prompt for extract here - /// if (WantExtract(e.FileName)) - /// e.Extract(); - /// } - /// } - /// - /// - /// Using zip1 As ZipFile = ZipFile.Read(ZipFileName) - /// Dim UpdatedPhotoShopFiles As ICollection(Of ZipEntry) = zip1.SelectEntries("*.psd", "UpdatedFiles") - /// Dim e As ZipEntry - /// For Each e In UpdatedPhotoShopFiles - /// ' prompt for extract here - /// If Me.WantExtract(e.FileName) Then - /// e.Extract - /// End If - /// Next - /// End Using - /// - /// - /// the string that specifies which entries to select - /// - /// - /// the directory in the archive from which to select entries. If null, then - /// all directories in the archive are used. - /// - /// - /// a collection of ZipEntry objects that conform to the inclusion spec - public ICollection SelectEntries(String selectionCriteria, string directoryPathInArchive) - { - Ionic.FileSelector ff = new Ionic.FileSelector(selectionCriteria, - AddDirectoryWillTraverseReparsePoints); - return ff.SelectEntries(this, directoryPathInArchive); - } - - - - /// - /// Remove entries from the zipfile by specified criteria. - /// - /// - /// - /// - /// This method allows callers to remove the collection of entries from the zipfile - /// that fit the specified criteria. The criteria are described in a string format, and - /// can include patterns for the filename; constraints on the size of the entry; - /// constraints on the last modified, created, or last accessed time for the file - /// described by the entry; or the attributes of the entry. - /// - /// - /// - /// For details on the syntax for the selectionCriteria parameter, see . - /// - /// - /// - /// This method is intended for use with a ZipFile that has been read from storage. - /// When creating a new ZipFile, this method will work only after the ZipArchive has - /// been Saved to the disk (the ZipFile class subsequently and implicitly reads the Zip - /// archive from storage.) Calling SelectEntries on a ZipFile that has not yet been - /// saved will deliver undefined results. - /// - /// - /// - /// - /// Thrown if selectionCriteria has an invalid syntax. - /// - /// - /// - /// This example removes all entries in a zip file that were modified prior to January 1st, 2008. - /// - /// using (ZipFile zip1 = ZipFile.Read(ZipFileName)) - /// { - /// // remove all entries from prior to Jan 1, 2008 - /// zip1.RemoveEntries("mtime < 2008-01-01"); - /// // don't forget to save the archive! - /// zip1.Save(); - /// } - /// - /// - /// Using zip As ZipFile = ZipFile.Read(ZipFileName) - /// ' remove all entries from prior to Jan 1, 2008 - /// zip1.RemoveEntries("mtime < 2008-01-01") - /// ' do not forget to save the archive! - /// zip1.Save - /// End Using - /// - /// - /// the string that specifies which entries to select - /// the number of entries removed - public int RemoveSelectedEntries(String selectionCriteria) - { - var selection = this.SelectEntries(selectionCriteria); - this.RemoveEntries(selection); - return selection.Count; - } - - - /// - /// Remove entries from the zipfile by specified criteria, and within the specified - /// path in the archive. - /// - /// - /// - /// - /// This method allows callers to remove the collection of entries from the zipfile - /// that fit the specified criteria. The criteria are described in a string format, and - /// can include patterns for the filename; constraints on the size of the entry; - /// constraints on the last modified, created, or last accessed time for the file - /// described by the entry; or the attributes of the entry. - /// - /// - /// - /// For details on the syntax for the selectionCriteria parameter, see . - /// - /// - /// - /// This method is intended for use with a ZipFile that has been read from storage. - /// When creating a new ZipFile, this method will work only after the ZipArchive has - /// been Saved to the disk (the ZipFile class subsequently and implicitly reads the Zip - /// archive from storage.) Calling SelectEntries on a ZipFile that has not yet been - /// saved will deliver undefined results. - /// - /// - /// - /// - /// Thrown if selectionCriteria has an invalid syntax. - /// - /// - /// - /// - /// using (ZipFile zip1 = ZipFile.Read(ZipFileName)) - /// { - /// // remove all entries from prior to Jan 1, 2008 - /// zip1.RemoveEntries("mtime < 2008-01-01", "documents"); - /// // a call to ZipFile.Save will make the modifications permanent - /// zip1.Save(); - /// } - /// - /// - /// Using zip As ZipFile = ZipFile.Read(ZipFileName) - /// ' remove all entries from prior to Jan 1, 2008 - /// zip1.RemoveEntries("mtime < 2008-01-01", "documents") - /// ' a call to ZipFile.Save will make the modifications permanent - /// zip1.Save - /// End Using - /// - /// - /// - /// the string that specifies which entries to select - /// - /// the directory in the archive from which to select entries. If null, then - /// all directories in the archive are used. - /// - /// the number of entries removed - public int RemoveSelectedEntries(String selectionCriteria, string directoryPathInArchive) - { - var selection = this.SelectEntries(selectionCriteria, directoryPathInArchive); - this.RemoveEntries(selection); - return selection.Count; - } - - - /// - /// Selects and Extracts a set of Entries from the ZipFile. - /// - /// - /// - /// - /// The entries are extracted into the current working directory. - /// - /// - /// - /// If any of the files to be extracted already exist, then the action taken is as - /// specified in the property on the - /// corresponding ZipEntry instance. By default, the action taken in this case is to - /// throw an exception. - /// - /// - /// - /// For information on the syntax of the selectionCriteria string, - /// see . - /// - /// - /// - /// - /// This example shows how extract all XML files modified after 15 January 2009. - /// - /// using (ZipFile zip = ZipFile.Read(zipArchiveName)) - /// { - /// zip.ExtractSelectedEntries("name = *.xml and mtime > 2009-01-15"); - /// } - /// - /// - /// the selection criteria for entries to extract. - /// - /// - public void ExtractSelectedEntries(String selectionCriteria) - { - foreach (ZipEntry e in SelectEntries(selectionCriteria)) - { - e.Password = _Password; // possibly null - e.Extract(); - } - } - - - /// - /// Selects and Extracts a set of Entries from the ZipFile. - /// - /// - /// - /// - /// The entries are extracted into the current working directory. When extraction would would - /// overwrite an existing filesystem file, the action taken is as specified in the - /// parameter. - /// - /// - /// - /// For information on the syntax of the string describing the entry selection criteria, - /// see . - /// - /// - /// - /// - /// This example shows how extract all XML files modified after 15 January 2009, - /// overwriting any existing files. - /// - /// using (ZipFile zip = ZipFile.Read(zipArchiveName)) - /// { - /// zip.ExtractSelectedEntries("name = *.xml and mtime > 2009-01-15", - /// ExtractExistingFileAction.OverwriteSilently); - /// } - /// - /// - /// - /// the selection criteria for entries to extract. - /// - /// - /// The action to take if extraction would overwrite an existing file. - /// - public void ExtractSelectedEntries(String selectionCriteria, ExtractExistingFileAction extractExistingFile) - { - foreach (ZipEntry e in SelectEntries(selectionCriteria)) - { - e.Password = _Password; // possibly null - e.Extract(extractExistingFile); - } - } - - - /// - /// Selects and Extracts a set of Entries from the ZipFile. - /// - /// - /// - /// - /// The entries are selected from the specified directory within the archive, and then - /// extracted into the current working directory. - /// - /// - /// - /// If any of the files to be extracted already exist, then the action taken is as - /// specified in the property on the - /// corresponding ZipEntry instance. By default, the action taken in this case is to - /// throw an exception. - /// - /// - /// - /// For information on the syntax of the string describing the entry selection criteria, - /// see . - /// - /// - /// - /// - /// This example shows how extract all XML files modified after 15 January 2009, - /// and writes them to the "unpack" directory. - /// - /// using (ZipFile zip = ZipFile.Read(zipArchiveName)) - /// { - /// zip.ExtractSelectedEntries("name = *.xml and mtime > 2009-01-15","unpack"); - /// } - /// - /// - /// - /// the selection criteria for entries to extract. - /// - /// - /// the directory in the archive from which to select entries. If null, then - /// all directories in the archive are used. - /// - /// - /// - public void ExtractSelectedEntries(String selectionCriteria, String directoryPathInArchive) - { - foreach (ZipEntry e in SelectEntries(selectionCriteria, directoryPathInArchive)) - { - e.Password = _Password; // possibly null - e.Extract(); - } - } - - - /// - /// Selects and Extracts a set of Entries from the ZipFile. - /// - /// - /// - /// - /// The entries are extracted into the specified directory. If any of the files to be - /// extracted already exist, an exception will be thrown. - /// - /// - /// For information on the syntax of the string describing the entry selection criteria, - /// see . - /// - /// - /// - /// the selection criteria for entries to extract. - /// - /// - /// the directory in the archive from which to select entries. If null, then - /// all directories in the archive are used. - /// - /// - /// - /// the directory on the disk into which to extract. It will be created - /// if it does not exist. - /// - public void ExtractSelectedEntries(String selectionCriteria, string directoryInArchive, string extractDirectory) - { - foreach (ZipEntry e in SelectEntries(selectionCriteria, directoryInArchive)) - { - e.Password = _Password; // possibly null - e.Extract(extractDirectory); - } - } - - - /// - /// Selects and Extracts a set of Entries from the ZipFile. - /// - /// - /// - /// - /// The entries are extracted into the specified directory. When extraction would would - /// overwrite an existing filesystem file, the action taken is as specified in the - /// parameter. - /// - /// - /// - /// For information on the syntax of the string describing the entry selection criteria, - /// see . - /// - /// - /// - /// - /// This example shows how extract all files with an XML extension or with a size larger than 100,000 bytes, - /// and puts them in the unpack directory. For any files that already exist in - /// that destination directory, they will not be overwritten. - /// - /// using (ZipFile zip = ZipFile.Read(zipArchiveName)) - /// { - /// zip.ExtractSelectedEntries("name = *.xml or size > 100000", - /// null, - /// "unpack", - /// ExtractExistingFileAction.DontOverwrite); - /// } - /// - /// - /// - /// the selection criteria for entries to extract. - /// - /// - /// The directory on the disk into which to extract. It will be created if it does not exist. - /// - /// - /// - /// The directory in the archive from which to select entries. If null, then - /// all directories in the archive are used. - /// - /// - /// - /// The action to take if extraction would overwrite an existing file. - /// - /// - public void ExtractSelectedEntries(String selectionCriteria, string directoryPathInArchive, string extractDirectory, ExtractExistingFileAction extractExistingFile) - { - foreach (ZipEntry e in SelectEntries(selectionCriteria, directoryPathInArchive)) - { - e.Password = _Password; // possibly null - e.Extract(extractDirectory, extractExistingFile); - } - } - - } - -} - - - -namespace Ionic -{ - internal abstract partial class SelectionCriterion - { - internal abstract bool Evaluate(Ionic.Zip.ZipEntry entry); - } - - - internal partial class NameCriterion : SelectionCriterion - { - internal override bool Evaluate(Ionic.Zip.ZipEntry entry) - { - // swap forward slashes in the entry.FileName for backslashes - string transformedFileName = entry.FileName.Replace("/", "\\"); - - return _Evaluate(transformedFileName); - } - } - - - internal partial class SizeCriterion : SelectionCriterion - { - internal override bool Evaluate(Ionic.Zip.ZipEntry entry) - { - return _Evaluate(entry.UncompressedSize); - } - } - - internal partial class TimeCriterion : SelectionCriterion - { - internal override bool Evaluate(Ionic.Zip.ZipEntry entry) - { - DateTime x; - switch (Which) - { - case WhichTime.atime: - x = entry.AccessedTime; - break; - case WhichTime.mtime: - x = entry.ModifiedTime; - break; - case WhichTime.ctime: - x = entry.CreationTime; - break; - default: throw new ArgumentException("??time"); - } - return _Evaluate(x); - } - } - - - internal partial class TypeCriterion : SelectionCriterion - { - internal override bool Evaluate(Ionic.Zip.ZipEntry entry) - { - bool result = (ObjectType == 'D') - ? entry.IsDirectory - : !entry.IsDirectory; - - if (Operator != ComparisonOperator.EqualTo) - result = !result; - return result; - } - } - -#if !SILVERLIGHT - internal partial class AttributesCriterion : SelectionCriterion - { - internal override bool Evaluate(Ionic.Zip.ZipEntry entry) - { - FileAttributes fileAttrs = entry.Attributes; - return _Evaluate(fileAttrs); - } - } -#endif - - internal partial class CompoundCriterion : SelectionCriterion - { - internal override bool Evaluate(Ionic.Zip.ZipEntry entry) - { - bool result = Left.Evaluate(entry); - switch (Conjunction) - { - case LogicalConjunction.AND: - if (result) - result = Right.Evaluate(entry); - break; - case LogicalConjunction.OR: - if (!result) - result = Right.Evaluate(entry); - break; - case LogicalConjunction.XOR: - result ^= Right.Evaluate(entry); - break; - } - return result; - } - } - - - - public partial class FileSelector - { - private bool Evaluate(Ionic.Zip.ZipEntry entry) - { - bool result = _Criterion.Evaluate(entry); - return result; - } - - /// - /// Retrieve the ZipEntry items in the ZipFile that conform to the specified criteria. - /// - /// - /// - /// - /// This method applies the criteria set in the FileSelector instance (as described in - /// the ) to the specified ZipFile. Using this - /// method, for example, you can retrieve all entries from the given ZipFile that - /// have filenames ending in .txt. - /// - /// - /// - /// Normally, applications would not call this method directly. This method is used - /// by the ZipFile class. - /// - /// - /// - /// Using the appropriate SelectionCriteria, you can retrieve entries based on size, - /// time, and attributes. See for a - /// description of the syntax of the SelectionCriteria string. - /// - /// - /// - /// - /// The ZipFile from which to retrieve entries. - /// - /// a collection of ZipEntry objects that conform to the criteria. - public ICollection SelectEntries(Ionic.Zip.ZipFile zip) - { - if (zip == null) - throw new ArgumentNullException("zip"); - - var list = new List(); - - foreach (Ionic.Zip.ZipEntry e in zip) - { - if (this.Evaluate(e)) - list.Add(e); - } - - return list; - } - - - /// - /// Retrieve the ZipEntry items in the ZipFile that conform to the specified criteria. - /// - /// - /// - /// - /// This method applies the criteria set in the FileSelector instance (as described in - /// the ) to the specified ZipFile. Using this - /// method, for example, you can retrieve all entries from the given ZipFile that - /// have filenames ending in .txt. - /// - /// - /// - /// Normally, applications would not call this method directly. This method is used - /// by the ZipFile class. - /// - /// - /// - /// This overload allows the selection of ZipEntry instances from the ZipFile to be restricted - /// to entries contained within a particular directory in the ZipFile. - /// - /// - /// - /// Using the appropriate SelectionCriteria, you can retrieve entries based on size, - /// time, and attributes. See for a - /// description of the syntax of the SelectionCriteria string. - /// - /// - /// - /// - /// The ZipFile from which to retrieve entries. - /// - /// - /// the directory in the archive from which to select entries. If null, then - /// all directories in the archive are used. - /// - /// - /// a collection of ZipEntry objects that conform to the criteria. - public ICollection SelectEntries(Ionic.Zip.ZipFile zip, string directoryPathInArchive) - { - if (zip == null) - throw new ArgumentNullException("zip"); - - var list = new List(); - // workitem 8559 - string slashSwapped = (directoryPathInArchive == null) ? null : directoryPathInArchive.Replace("/", "\\"); - // workitem 9174 - if (slashSwapped != null) - { - while (slashSwapped.EndsWith("\\")) - slashSwapped = slashSwapped.Substring(0, slashSwapped.Length - 1); - } - foreach (Ionic.Zip.ZipEntry e in zip) - { - if (directoryPathInArchive == null || (Path.GetDirectoryName(e.FileName) == directoryPathInArchive) - || (Path.GetDirectoryName(e.FileName) == slashSwapped)) // workitem 8559 - if (this.Evaluate(e)) - list.Add(e); - } - - return list; - } - - } -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.cs deleted file mode 100644 index b127a925..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.cs +++ /dev/null @@ -1,3910 +0,0 @@ -// ZipFile.cs -// -// Copyright (c) 2006-2010 Dino Chiesa -// All rights reserved. -// -// This module is part of DotNetZip, a zipfile class library. -// The class library reads and writes zip files, according to the format -// described by PKware, at: -// http://www.pkware.com/business_and_developers/developer/popups/appnote.txt -// -// -// There are other Zip class libraries available. -// -// - it is possible to read and write zip files within .NET via the J# runtime. -// But some people don't like to install the extra DLL, which is no longer -// supported by MS. And also, the J# libraries don't support advanced zip -// features, like ZIP64, spanned archives, or AES encryption. -// -// - There are third-party GPL and LGPL libraries available. Some people don't -// like the license, and some of them don't support all the ZIP features, like AES. -// -// - Finally, there are commercial tools (From ComponentOne, XCeed, etc). But -// some people don't want to incur the cost. -// -// This alternative implementation is **not** GPL licensed. It is free of cost, and -// does not require J#. It does require .NET 2.0. It balances a good set of -// features, with ease of use and speed of performance. -// -// This code is released under the Microsoft Public License . -// See the License.txt for details. -// -// -// NB: This implementation originally relied on the -// System.IO.Compression.DeflateStream base class in the .NET Framework -// v2.0 base class library, but now includes a managed-code port of Zlib. -// -// Thu, 08 Oct 2009 17:04 -// - - -using System; -using System.IO; -using System.Collections.Generic; -using Interop = System.Runtime.InteropServices; - - -namespace Ionic.Zip -{ - /// - /// The ZipFile type represents a zip archive file. - /// - /// - /// - /// - /// This is the main type in the DotNetZip class library. This class reads and - /// writes zip files, as defined in the specification - /// for zip files described by PKWare. The compression for this - /// implementation is provided by a managed-code version of Zlib, included with - /// DotNetZip in the classes in the Ionic.Zlib namespace. - /// - /// - /// - /// This class provides a general purpose zip file capability. Use it to read, - /// create, or update zip files. When you want to create zip files using a - /// Stream type to write the zip file, you may want to consider the class. - /// - /// - /// - /// Both the ZipOutputStream class and the ZipFile class can - /// be used to create zip files. Both of them support many of the common zip - /// features, including Unicode, different compression methods and levels, - /// and ZIP64. They provide very similar performance when creating zip - /// files. - /// - /// - /// - /// The ZipFile class is generally easier to use than - /// ZipOutputStream and should be considered a higher-level interface. For - /// example, when creating a zip file via calls to the PutNextEntry() and - /// Write() methods on the ZipOutputStream class, the caller is - /// responsible for opening the file, reading the bytes from the file, writing - /// those bytes into the ZipOutputStream, setting the attributes on the - /// ZipEntry, and setting the created, last modified, and last accessed - /// timestamps on the zip entry. All of these things are done automatically by a - /// call to ZipFile.AddFile(). - /// For this reason, the ZipOutputStream is generally recommended for use - /// only when your application emits arbitrary data, not necessarily data from a - /// filesystem file, directly into a zip file, and does so using a Stream - /// metaphor. - /// - /// - /// - /// Aside from the differences in programming model, there are other - /// differences in capability between the two classes. - /// - /// - /// - /// - /// ZipFile can be used to read and extract zip files, in addition to - /// creating zip files. ZipOutputStream cannot read zip files. If you want - /// to use a stream to read zip files, check out the class. - /// - /// - /// - /// ZipOutputStream does not support the creation of segmented or spanned - /// zip files. - /// - /// - /// - /// ZipOutputStream cannot produce a self-extracting archive. - /// - /// - /// - /// - /// Be aware that the ZipFile class implements the interface. In order for ZipFile to - /// produce a valid zip file, you use use it within a using clause (Using - /// in VB), or call the Dispose() method explicitly. See the examples - /// for how to employ a using clause. - /// - /// - /// - [Interop.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d00005")] - [Interop.ComVisible(true)] -#if !NETCF - [Interop.ClassInterface(Interop.ClassInterfaceType.AutoDispatch)] -#endif - public partial class ZipFile : - System.Collections.IEnumerable, - System.Collections.Generic.IEnumerable, - IDisposable - { - - #region public properties - - /// - /// Indicates whether to perform a full scan of the zip file when reading it. - /// - /// - /// - /// - /// - /// You almost never want to use this property. - /// - /// - /// - /// When reading a zip file, if this flag is true (True in - /// VB), the entire zip archive will be scanned and searched for entries. - /// For large archives, this can take a very, long time. The much more - /// efficient default behavior is to read the zip directory, which is - /// stored at the end of the zip file. But, in some cases the directory is - /// corrupted and you need to perform a full scan of the zip file to - /// determine the contents of the zip file. This property lets you do - /// that, when necessary. - /// - /// - /// - /// This flag is effective only when calling . Normally you would read a ZipFile with the - /// static ZipFile.Read - /// method. But you can't set the FullScan property on the - /// ZipFile instance when you use a static factory method like - /// ZipFile.Read. - /// - /// - /// - /// - /// - /// - /// This example shows how to read a zip file using the full scan approach, - /// and then save it, thereby producing a corrected zip file. - /// - /// - /// using (var zip = new ZipFile()) - /// { - /// zip.FullScan = true; - /// zip.Initialize(zipFileName); - /// zip.Save(newName); - /// } - /// - /// - /// - /// Using zip As New ZipFile - /// zip.FullScan = True - /// zip.Initialize(zipFileName) - /// zip.Save(newName) - /// End Using - /// - /// - /// - public bool FullScan - { - get; - set; - } - - - /// - /// Whether to sort the ZipEntries before saving the file. - /// - /// - /// - /// The default is false. If you have a large number of zip entries, the sort - /// alone can consume significant time. - /// - /// - /// - /// - /// using (var zip = new ZipFile()) - /// { - /// zip.AddFiles(filesToAdd); - /// zip.SortEntriesBeforeSaving = true; - /// zip.Save(name); - /// } - /// - /// - /// - /// Using zip As New ZipFile - /// zip.AddFiles(filesToAdd) - /// zip.SortEntriesBeforeSaving = True - /// zip.Save(name) - /// End Using - /// - /// - /// - public bool SortEntriesBeforeSaving - { - get; - set; - } - - - - /// - /// Indicates whether NTFS Reparse Points, like junctions, should be - /// traversed during calls to AddDirectory(). - /// - /// - /// - /// By default, calls to AddDirectory() will traverse NTFS reparse - /// points, like mounted volumes, and directory junctions. An example - /// of a junction is the "My Music" directory in Windows Vista. In some - /// cases you may not want DotNetZip to traverse those directories. In - /// that case, set this property to false. - /// - /// - /// - /// - /// using (var zip = new ZipFile()) - /// { - /// zip.AddDirectoryWillTraverseReparsePoints = false; - /// zip.AddDirectory(dirToZip,"fodder"); - /// zip.Save(zipFileToCreate); - /// } - /// - /// - public bool AddDirectoryWillTraverseReparsePoints { get; set; } - - - /// - /// Size of the IO buffer used while saving. - /// - /// - /// - /// - /// - /// First, let me say that you really don't need to bother with this. It is - /// here to allow for optimizations that you probably won't make! It will work - /// fine if you don't set or get this property at all. Ok? - /// - /// - /// - /// Now that we have that out of the way, the fine print: This - /// property affects the size of the buffer that is used for I/O for each - /// entry contained in the zip file. When a file is read in to be compressed, - /// it uses a buffer given by the size here. When you update a zip file, the - /// data for unmodified entries is copied from the first zip file to the - /// other, through a buffer given by the size here. - /// - /// - /// - /// Changing the buffer size affects a few things: first, for larger buffer - /// sizes, the memory used by the ZipFile, obviously, will be larger - /// during I/O operations. This may make operations faster for very much - /// larger files. Last, for any given entry, when you use a larger buffer - /// there will be fewer progress events during I/O operations, because there's - /// one progress event generated for each time the buffer is filled and then - /// emptied. - /// - /// - /// - /// The default buffer size is 8k. Increasing the buffer size may speed - /// things up as you compress larger files. But there are no hard-and-fast - /// rules here, eh? You won't know til you test it. And there will be a - /// limit where ever larger buffers actually slow things down. So as I said - /// in the beginning, it's probably best if you don't set or get this property - /// at all. - /// - /// - /// - /// - /// - /// This example shows how you might set a large buffer size for efficiency when - /// dealing with zip entries that are larger than 1gb. - /// - /// using (ZipFile zip = new ZipFile()) - /// { - /// zip.SaveProgress += this.zip1_SaveProgress; - /// zip.AddDirectory(directoryToZip, ""); - /// zip.UseZip64WhenSaving = Zip64Option.Always; - /// zip.BufferSize = 65536*8; // 65536 * 8 = 512k - /// zip.Save(ZipFileToCreate); - /// } - /// - /// - - public int BufferSize - { - get { return _BufferSize; } - set { _BufferSize = value; } - } - - /// - /// Size of the work buffer to use for the ZLIB codec during compression. - /// - /// - /// - /// - /// When doing ZLIB or Deflate compression, the library fills a buffer, - /// then passes it to the compressor for compression. Then the library - /// reads out the compressed bytes. This happens repeatedly until there - /// is no more uncompressed data to compress. This property sets the - /// size of the buffer that will be used for chunk-wise compression. In - /// order for the setting to take effect, your application needs to set - /// this property before calling one of the ZipFile.Save() - /// overloads. - /// - /// - /// Setting this affects the performance and memory efficiency of - /// compression and decompression. For larger files, setting this to a - /// larger size may improve compression performance, but the exact - /// numbers vary depending on available memory, the size of the streams - /// you are compressing, and a bunch of other variables. I don't have - /// good firm recommendations on how to set it. You'll have to test it - /// yourself. Or just leave it alone and accept the default. - /// - /// - public int CodecBufferSize - { - get; - set; - } - - /// - /// Indicates whether extracted files should keep their paths as - /// stored in the zip archive. - /// - /// - /// - /// - /// This property affects Extraction. It is not used when creating zip - /// archives. - /// - /// - /// - /// With this property set to false, the default, extracting entries - /// from a zip file will create files in the filesystem that have the full - /// path associated to the entry within the zip file. With this property set - /// to true, extracting entries from the zip file results in files - /// with no path: the folders are "flattened." - /// - /// - /// - /// An example: suppose the zip file contains entries /directory1/file1.txt and - /// /directory2/file2.txt. With FlattenFoldersOnExtract set to false, - /// the files created will be \directory1\file1.txt and \directory2\file2.txt. - /// With the property set to true, the files created are file1.txt and file2.txt. - /// - /// - /// - public bool FlattenFoldersOnExtract - { - get; - set; - } - - - /// - /// The compression strategy to use for all entries. - /// - /// - /// - /// Set the Strategy used by the ZLIB-compatible compressor, when - /// compressing entries using the DEFLATE method. Different compression - /// strategies work better on different sorts of data. The strategy - /// parameter can affect the compression ratio and the speed of - /// compression but not the correctness of the compresssion. For more - /// information see Ionic.Zlib.CompressionStrategy. - /// - public Ionic.Zlib.CompressionStrategy Strategy - { - get { return _Strategy; } - set { _Strategy = value; } - } - - - /// - /// The name of the ZipFile, on disk. - /// - /// - /// - /// - /// - /// When the ZipFile instance was created by reading an archive using - /// one of the ZipFile.Read methods, this property represents the name - /// of the zip file that was read. When the ZipFile instance was - /// created by using the no-argument constructor, this value is null - /// (Nothing in VB). - /// - /// - /// - /// If you use the no-argument constructor, and you then explicitly set this - /// property, when you call , this name will - /// specify the name of the zip file created. Doing so is equivalent to - /// calling . When instantiating a - /// ZipFile by reading from a stream or byte array, the Name - /// property remains null. When saving to a stream, the Name - /// property is implicitly set to null. - /// - /// - public string Name - { - get { return _name; } - set { _name = value; } - } - - - /// - /// Sets the compression level to be used for entries subsequently added to - /// the zip archive. - /// - /// - /// - /// - /// Varying the compression level used on entries can affect the - /// size-vs-speed tradeoff when compression and decompressing data streams - /// or files. - /// - /// - /// - /// As with some other properties on the ZipFile class, like , , and , setting this property on a ZipFile - /// instance will cause the specified CompressionLevel to be used on all - /// items that are subsequently added to the - /// ZipFile instance. If you set this property after you have added - /// items to the ZipFile, but before you have called Save(), - /// those items will not use the specified compression level. - /// - /// - /// - /// If you do not set this property, the default compression level is used, - /// which normally gives a good balance of compression efficiency and - /// compression speed. In some tests, using BestCompression can - /// double the time it takes to compress, while delivering just a small - /// increase in compression efficiency. This behavior will vary with the - /// type of data you compress. If you are in doubt, just leave this setting - /// alone, and accept the default. - /// - /// - public Ionic.Zlib.CompressionLevel CompressionLevel - { - get; - set; - } - - /// - /// The compression method for the zipfile. - /// - /// - /// - /// By default, the compression method is CompressionMethod.Deflate. - /// - /// - /// - public Ionic.Zip.CompressionMethod CompressionMethod - { - get - { - return _compressionMethod; - } - set - { - _compressionMethod = value; - } - } - - - - /// - /// A comment attached to the zip archive. - /// - /// - /// - /// - /// - /// This property is read/write. It allows the application to specify a - /// comment for the ZipFile, or read the comment for the - /// ZipFile. After setting this property, changes are only made - /// permanent when you call a Save() method. - /// - /// - /// - /// According to PKWARE's - /// zip specification, the comment is not encrypted, even if there is a - /// password set on the zip file. - /// - /// - /// - /// The specification does not describe how to indicate the encoding used - /// on a comment string. Many "compliant" zip tools and libraries use - /// IBM437 as the code page for comments; DotNetZip, too, follows that - /// practice. On the other hand, there are situations where you want a - /// Comment to be encoded with something else, for example using code page - /// 950 "Big-5 Chinese". To fill that need, DotNetZip will encode the - /// comment following the same procedure it follows for encoding - /// filenames: (a) if is - /// Never, it uses the default encoding (IBM437). (b) if is Always, it always uses the - /// alternate encoding (). (c) if is AsNecessary, it uses the - /// alternate encoding only if the default encoding is not sufficient for - /// encoding the comment - in other words if decoding the result does not - /// produce the original string. This decision is taken at the time of - /// the call to ZipFile.Save(). - /// - /// - /// - /// When creating a zip archive using this library, it is possible to change - /// the value of between each - /// entry you add, and between adding entries and the call to - /// Save(). Don't do this. It will likely result in a zip file that is - /// not readable by any tool or application. For best interoperability, leave - /// alone, or specify it only - /// once, before adding any entries to the ZipFile instance. - /// - /// - /// - public string Comment - { - get { return _Comment; } - set - { - _Comment = value; - _contentsChanged = true; - } - } - - - - - /// - /// Specifies whether the Creation, Access, and Modified times for entries - /// added to the zip file will be emitted in “Windows format” - /// when the zip archive is saved. - /// - /// - /// - /// - /// An application creating a zip archive can use this flag to explicitly - /// specify that the file times for the entries should or should not be stored - /// in the zip archive in the format used by Windows. By default this flag is - /// true, meaning the Windows-format times are stored in the zip - /// archive. - /// - /// - /// - /// When adding an entry from a file or directory, the Creation (), Access (), and Modified () times for the given entry are - /// automatically set from the filesystem values. When adding an entry from a - /// stream or string, all three values are implicitly set to - /// DateTime.Now. Applications can also explicitly set those times by - /// calling . - /// - /// - /// - /// PKWARE's - /// zip specification describes multiple ways to format these times in a - /// zip file. One is the format Windows applications normally use: 100ns ticks - /// since January 1, 1601 UTC. The other is a format Unix applications typically - /// use: seconds since January 1, 1970 UTC. Each format can be stored in an - /// "extra field" in the zip entry when saving the zip archive. The former - /// uses an extra field with a Header Id of 0x000A, while the latter uses a - /// header ID of 0x5455, although you probably don't need to know that. - /// - /// - /// - /// Not all tools and libraries can interpret these fields. Windows - /// compressed folders is one that can read the Windows Format timestamps, - /// while I believe the Infozip - /// tools can read the Unix format timestamps. Some tools and libraries - /// may be able to read only one or the other. DotNetZip can read or write - /// times in either or both formats. - /// - /// - /// - /// The times stored are taken from , , and . - /// - /// - /// - /// The value set here applies to all entries subsequently added to the - /// ZipFile. - /// - /// - /// - /// This property is not mutually exclusive of the property. It is possible and - /// legal and valid to produce a zip file that contains timestamps encoded in - /// the Unix format as well as in the Windows format, in addition to the LastModified time attached to each - /// entry in the archive, a time that is always stored in "DOS format". And, - /// notwithstanding the names PKWare uses for these time formats, any of them - /// can be read and written by any computer, on any operating system. But, - /// there are no guarantees that a program running on Mac or Linux will - /// gracefully handle a zip file with "Windows" formatted times, or that an - /// application that does not use DotNetZip but runs on Windows will be able to - /// handle file times in Unix format. - /// - /// - /// - /// When in doubt, test. Sorry, I haven't got a complete list of tools and - /// which sort of timestamps they can use and will tolerate. If you get any - /// good information and would like to pass it on, please do so and I will - /// include that information in this documentation. - /// - /// - /// - /// - /// This example shows how to save a zip file that contains file timestamps - /// in a format normally used by Unix. - /// - /// using (var zip = new ZipFile()) - /// { - /// // produce a zip file the Mac will like - /// zip.EmitTimesInWindowsFormatWhenSaving = false; - /// zip.EmitTimesInUnixFormatWhenSaving = true; - /// zip.AddDirectory(directoryToZip, "files"); - /// zip.Save(outputFile); - /// } - /// - /// - /// - /// Using zip As New ZipFile - /// '' produce a zip file the Mac will like - /// zip.EmitTimesInWindowsFormatWhenSaving = False - /// zip.EmitTimesInUnixFormatWhenSaving = True - /// zip.AddDirectory(directoryToZip, "files") - /// zip.Save(outputFile) - /// End Using - /// - /// - /// - /// - /// - public bool EmitTimesInWindowsFormatWhenSaving - { - get - { - return _emitNtfsTimes; - } - set - { - _emitNtfsTimes = value; - } - } - - - /// - /// Specifies whether the Creation, Access, and Modified times - /// for entries added to the zip file will be emitted in "Unix(tm) - /// format" when the zip archive is saved. - /// - /// - /// - /// - /// An application creating a zip archive can use this flag to explicitly - /// specify that the file times for the entries should or should not be stored - /// in the zip archive in the format used by Unix. By default this flag is - /// false, meaning the Unix-format times are not stored in the zip - /// archive. - /// - /// - /// - /// When adding an entry from a file or directory, the Creation (), Access (), and Modified () times for the given entry are - /// automatically set from the filesystem values. When adding an entry from a - /// stream or string, all three values are implicitly set to DateTime.Now. - /// Applications can also explicitly set those times by calling . - /// - /// - /// - /// PKWARE's - /// zip specification describes multiple ways to format these times in a - /// zip file. One is the format Windows applications normally use: 100ns ticks - /// since January 1, 1601 UTC. The other is a format Unix applications - /// typically use: seconds since January 1, 1970 UTC. Each format can be - /// stored in an "extra field" in the zip entry when saving the zip - /// archive. The former uses an extra field with a Header Id of 0x000A, while - /// the latter uses a header ID of 0x5455, although you probably don't need to - /// know that. - /// - /// - /// - /// Not all tools and libraries can interpret these fields. Windows - /// compressed folders is one that can read the Windows Format timestamps, - /// while I believe the Infozip - /// tools can read the Unix format timestamps. Some tools and libraries may be - /// able to read only one or the other. DotNetZip can read or write times in - /// either or both formats. - /// - /// - /// - /// The times stored are taken from , , and . - /// - /// - /// - /// This property is not mutually exclusive of the property. It is possible and - /// legal and valid to produce a zip file that contains timestamps encoded in - /// the Unix format as well as in the Windows format, in addition to the LastModified time attached to each - /// entry in the zip archive, a time that is always stored in "DOS - /// format". And, notwithstanding the names PKWare uses for these time - /// formats, any of them can be read and written by any computer, on any - /// operating system. But, there are no guarantees that a program running on - /// Mac or Linux will gracefully handle a zip file with "Windows" formatted - /// times, or that an application that does not use DotNetZip but runs on - /// Windows will be able to handle file times in Unix format. - /// - /// - /// - /// When in doubt, test. Sorry, I haven't got a complete list of tools and - /// which sort of timestamps they can use and will tolerate. If you get any - /// good information and would like to pass it on, please do so and I will - /// include that information in this documentation. - /// - /// - /// - /// - /// - public bool EmitTimesInUnixFormatWhenSaving - { - get - { - return _emitUnixTimes; - } - set - { - _emitUnixTimes = value; - } - } - - - - /// - /// Indicates whether verbose output is sent to the during AddXxx() and - /// ReadXxx() operations. - /// - /// - /// - /// This is a synthetic property. It returns true if the is non-null. - /// - internal bool Verbose - { - get { return (_StatusMessageTextWriter != null); } - } - - - /// - /// Returns true if an entry by the given name exists in the ZipFile. - /// - /// - /// the name of the entry to find - /// true if an entry with the given name exists; otherwise false. - /// - public bool ContainsEntry(string name) - { - // workitem 12534 - return _entries.ContainsKey(SharedUtilities.NormalizePathForUseInZipFile(name)); - } - - - - /// - /// Indicates whether to perform case-sensitive matching on the filename when - /// retrieving entries in the zipfile via the string-based indexer. - /// - /// - /// - /// The default value is false, which means don't do case-sensitive - /// matching. In other words, retrieving zip["ReadMe.Txt"] is the same as - /// zip["readme.txt"]. It really makes sense to set this to true only - /// if you are not running on Windows, which has case-insensitive - /// filenames. But since this library is not built for non-Windows platforms, - /// in most cases you should just leave this property alone. - /// - public bool CaseSensitiveRetrieval - { - get - { - return _CaseSensitiveRetrieval; - } - - set - { - // workitem 9868 - if (value != _CaseSensitiveRetrieval) - { - _CaseSensitiveRetrieval = value; - _initEntriesDictionary(); - } - } - } - - - /// - /// Indicates whether to encode entry filenames and entry comments using Unicode - /// (UTF-8). - /// - /// - /// - /// - /// The - /// PKWare zip specification provides for encoding file names and file - /// comments in either the IBM437 code page, or in UTF-8. This flag selects - /// the encoding according to that specification. By default, this flag is - /// false, and filenames and comments are encoded into the zip file in the - /// IBM437 codepage. Setting this flag to true will specify that filenames - /// and comments that cannot be encoded with IBM437 will be encoded with - /// UTF-8. - /// - /// - /// - /// Zip files created with strict adherence to the PKWare specification with - /// respect to UTF-8 encoding can contain entries with filenames containing - /// any combination of Unicode characters, including the full range of - /// characters from Chinese, Latin, Hebrew, Greek, Cyrillic, and many other - /// alphabets. However, because at this time, the UTF-8 portion of the PKWare - /// specification is not broadly supported by other zip libraries and - /// utilities, such zip files may not be readable by your favorite zip tool or - /// archiver. In other words, interoperability will decrease if you set this - /// flag to true. - /// - /// - /// - /// In particular, Zip files created with strict adherence to the PKWare - /// specification with respect to UTF-8 encoding will not work well with - /// Explorer in Windows XP or Windows Vista, because Windows compressed - /// folders, as far as I know, do not support UTF-8 in zip files. Vista can - /// read the zip files, but shows the filenames incorrectly. Unpacking from - /// Windows Vista Explorer will result in filenames that have rubbish - /// characters in place of the high-order UTF-8 bytes. - /// - /// - /// - /// Also, zip files that use UTF-8 encoding will not work well with Java - /// applications that use the java.util.zip classes, as of v5.0 of the Java - /// runtime. The Java runtime does not correctly implement the PKWare - /// specification in this regard. - /// - /// - /// - /// As a result, we have the unfortunate situation that "correct" behavior by - /// the DotNetZip library with regard to Unicode encoding of filenames during - /// zip creation will result in zip files that are readable by strictly - /// compliant and current tools (for example the most recent release of the - /// commercial WinZip tool); but these zip files will not be readable by - /// various other tools or libraries, including Windows Explorer. - /// - /// - /// - /// The DotNetZip library can read and write zip files with UTF8-encoded - /// entries, according to the PKware spec. If you use DotNetZip for both - /// creating and reading the zip file, and you use UTF-8, there will be no - /// loss of information in the filenames. For example, using a self-extractor - /// created by this library will allow you to unpack files correctly with no - /// loss of information in the filenames. - /// - /// - /// - /// If you do not set this flag, it will remain false. If this flag is false, - /// your ZipFile will encode all filenames and comments using the - /// IBM437 codepage. This can cause "loss of information" on some filenames, - /// but the resulting zipfile will be more interoperable with other - /// utilities. As an example of the loss of information, diacritics can be - /// lost. The o-tilde character will be down-coded to plain o. The c with a - /// cedilla (Unicode 0xE7) used in Portugese will be downcoded to a c. - /// Likewise, the O-stroke character (Unicode 248), used in Danish and - /// Norwegian, will be down-coded to plain o. Chinese characters cannot be - /// represented in codepage IBM437; when using the default encoding, Chinese - /// characters in filenames will be represented as ?. These are all examples - /// of "information loss". - /// - /// - /// - /// The loss of information associated to the use of the IBM437 encoding is - /// inconvenient, and can also lead to runtime errors. For example, using - /// IBM437, any sequence of 4 Chinese characters will be encoded as ????. If - /// your application creates a ZipFile, then adds two files, each with - /// names of four Chinese characters each, this will result in a duplicate - /// filename exception. In the case where you add a single file with a name - /// containing four Chinese characters, calling Extract() on the entry that - /// has question marks in the filename will result in an exception, because - /// the question mark is not legal for use within filenames on Windows. These - /// are just a few examples of the problems associated to loss of information. - /// - /// - /// - /// This flag is independent of the encoding of the content within the entries - /// in the zip file. Think of the zip file as a container - it supports an - /// encoding. Within the container are other "containers" - the file entries - /// themselves. The encoding within those entries is independent of the - /// encoding of the zip archive container for those entries. - /// - /// - /// - /// Rather than specify the encoding in a binary fashion using this flag, an - /// application can specify an arbitrary encoding via the property. Setting the encoding - /// explicitly when creating zip archives will result in non-compliant zip - /// files that, curiously, are fairly interoperable. The challenge is, the - /// PKWare specification does not provide for a way to specify that an entry - /// in a zip archive uses a code page that is neither IBM437 nor UTF-8. - /// Therefore if you set the encoding explicitly when creating a zip archive, - /// you must take care upon reading the zip archive to use the same code page. - /// If you get it wrong, the behavior is undefined and may result in incorrect - /// filenames, exceptions, stomach upset, hair loss, and acne. - /// - /// - /// - [Obsolete("Beginning with v1.9.1.6 of DotNetZip, this property is obsolete. It will be removed in a future version of the library. Your applications should use AlternateEncoding and AlternateEncodingUsage instead.")] - public bool UseUnicodeAsNecessary - { - get - { - return (_alternateEncoding == System.Text.Encoding.GetEncoding("UTF-8")) && - (_alternateEncodingUsage == ZipOption.AsNecessary); - } - set - { - if (value) - { - _alternateEncoding = System.Text.Encoding.GetEncoding("UTF-8"); - _alternateEncodingUsage = ZipOption.AsNecessary; - - } - else - { - _alternateEncoding = Ionic.Zip.ZipFile.DefaultEncoding; - _alternateEncodingUsage = ZipOption.Never; - } - } - } - - - /// - /// Specify whether to use ZIP64 extensions when saving a zip archive. - /// - /// - /// - /// - /// - /// When creating a zip file, the default value for the property is . is - /// safest, in the sense that you will not get an Exception if a pre-ZIP64 - /// limit is exceeded. - /// - /// - /// - /// You may set the property at any time before calling Save(). - /// - /// - /// - /// When reading a zip file via the Zipfile.Read() method, DotNetZip - /// will properly read ZIP64-endowed zip archives, regardless of the value of - /// this property. DotNetZip will always read ZIP64 archives. This property - /// governs only whether DotNetZip will write them. Therefore, when updating - /// archives, be careful about setting this property after reading an archive - /// that may use ZIP64 extensions. - /// - /// - /// - /// An interesting question is, if you have set this property to - /// AsNecessary, and then successfully saved, does the resulting - /// archive use ZIP64 extensions or not? To learn this, check the property, after calling Save(). - /// - /// - /// - /// Have you thought about - /// donating? - /// - /// - /// - /// - public Zip64Option UseZip64WhenSaving - { - get - { - return _zip64; - } - set - { - _zip64 = value; - } - } - - - - /// - /// Indicates whether the archive requires ZIP64 extensions. - /// - /// - /// - /// - /// - /// This property is null (or Nothing in VB) if the archive has - /// not been saved, and there are fewer than 65334 ZipEntry items - /// contained in the archive. - /// - /// - /// - /// The Value is true if any of the following four conditions holds: - /// the uncompressed size of any entry is larger than 0xFFFFFFFF; the - /// compressed size of any entry is larger than 0xFFFFFFFF; the relative - /// offset of any entry within the zip archive is larger than 0xFFFFFFFF; or - /// there are more than 65534 entries in the archive. (0xFFFFFFFF = - /// 4,294,967,295). The result may not be known until a Save() is attempted - /// on the zip archive. The Value of this - /// property may be set only AFTER one of the Save() methods has been called. - /// - /// - /// - /// If none of the four conditions holds, and the archive has been saved, then - /// the Value is false. - /// - /// - /// - /// A Value of false does not indicate that the zip archive, as saved, - /// does not use ZIP64. It merely indicates that ZIP64 is not required. An - /// archive may use ZIP64 even when not required if the property is set to , or if the property is set to and the output stream was not - /// seekable. Use the property to determine if - /// the most recent Save() method resulted in an archive that utilized - /// the ZIP64 extensions. - /// - /// - /// - /// - /// - public Nullable RequiresZip64 - { - get - { - if (_entries.Count > 65534) - return new Nullable(true); - - // If the ZipFile has not been saved or if the contents have changed, then - // it is not known if ZIP64 is required. - if (!_hasBeenSaved || _contentsChanged) return null; - - // Whether ZIP64 is required is knowable. - foreach (ZipEntry e in _entries.Values) - { - if (e.RequiresZip64.Value) return new Nullable(true); - } - - return new Nullable(false); - } - } - - - /// - /// Indicates whether the most recent Save() operation used ZIP64 extensions. - /// - /// - /// - /// - /// The use of ZIP64 extensions within an archive is not always necessary, and - /// for interoperability concerns, it may be desired to NOT use ZIP64 if - /// possible. The property can be - /// set to use ZIP64 extensions only when necessary. In those cases, - /// Sometimes applications want to know whether a Save() actually used ZIP64 - /// extensions. Applications can query this read-only property to learn - /// whether ZIP64 has been used in a just-saved ZipFile. - /// - /// - /// - /// The value is null (or Nothing in VB) if the archive has not - /// been saved. - /// - /// - /// - /// Non-null values (HasValue is true) indicate whether ZIP64 - /// extensions were used during the most recent Save() operation. The - /// ZIP64 extensions may have been used as required by any particular entry - /// because of its uncompressed or compressed size, or because the archive is - /// larger than 4294967295 bytes, or because there are more than 65534 entries - /// in the archive, or because the UseZip64WhenSaving property was set - /// to , or because the - /// UseZip64WhenSaving property was set to and the output stream was not seekable. - /// The value of this property does not indicate the reason the ZIP64 - /// extensions were used. - /// - /// - /// - /// - /// - public Nullable OutputUsedZip64 - { - get - { - return _OutputUsesZip64; - } - } - - - /// - /// Indicates whether the most recent Read() operation read a zip file that uses - /// ZIP64 extensions. - /// - /// - /// - /// This property will return null (Nothing in VB) if you've added an entry after reading - /// the zip file. - /// - public Nullable InputUsesZip64 - { - get - { - if (_entries.Count > 65534) - return true; - - foreach (ZipEntry e in this) - { - // if any entry was added after reading the zip file, then the result is null - if (e.Source != ZipEntrySource.ZipFile) return null; - - // if any entry read from the zip used zip64, then the result is true - if (e._InputUsesZip64) return true; - } - return false; - } - } - - - /// - /// The text encoding to use when writing new entries to the ZipFile, - /// for those entries that cannot be encoded with the default (IBM437) - /// encoding; or, the text encoding that was used when reading the entries - /// from the ZipFile. - /// - /// - /// - /// - /// In its - /// zip specification, PKWare describes two options for encoding - /// filenames and comments: using IBM437 or UTF-8. But, some archiving tools - /// or libraries do not follow the specification, and instead encode - /// characters using the system default code page. For example, WinRAR when - /// run on a machine in Shanghai may encode filenames with the Big-5 Chinese - /// (950) code page. This behavior is contrary to the Zip specification, but - /// it occurs anyway. - /// - /// - /// - /// When using DotNetZip to write zip archives that will be read by one of - /// these other archivers, set this property to specify the code page to use - /// when encoding the and for each ZipEntry in the zip file, for - /// values that cannot be encoded with the default codepage for zip files, - /// IBM437. This is why this property is "provisional". In all cases, IBM437 - /// is used where possible, in other words, where no loss of data would - /// result. It is possible, therefore, to have a given entry with a - /// Comment encoded in IBM437 and a FileName encoded with the - /// specified "provisional" codepage. - /// - /// - /// - /// Be aware that a zip file created after you've explicitly set the property to a value other than - /// IBM437 may not be compliant to the PKWare specification, and may not be - /// readable by compliant archivers. On the other hand, many (most?) - /// archivers are non-compliant and can read zip files created in arbitrary - /// code pages. The trick is to use or specify the proper codepage when - /// reading the zip. - /// - /// - /// - /// When creating a zip archive using this library, it is possible to change - /// the value of between each - /// entry you add, and between adding entries and the call to - /// Save(). Don't do this. It will likely result in a zipfile that is - /// not readable. For best interoperability, either leave alone, or specify it only once, - /// before adding any entries to the ZipFile instance. There is one - /// exception to this recommendation, described later. - /// - /// - /// - /// When using an arbitrary, non-UTF8 code page for encoding, there is no - /// standard way for the creator application - whether DotNetZip, WinZip, - /// WinRar, or something else - to formally specify in the zip file which - /// codepage has been used for the entries. As a result, readers of zip files - /// are not able to inspect the zip file and determine the codepage that was - /// used for the entries contained within it. It is left to the application - /// or user to determine the necessary codepage when reading zip files encoded - /// this way. In other words, if you explicitly specify the codepage when you - /// create the zipfile, you must explicitly specify the same codepage when - /// reading the zipfile. - /// - /// - /// - /// The way you specify the code page to use when reading a zip file varies - /// depending on the tool or library you use to read the zip. In DotNetZip, - /// you use a ZipFile.Read() method that accepts an encoding parameter. It - /// isn't possible with Windows Explorer, as far as I know, to specify an - /// explicit codepage to use when reading a zip. If you use an incorrect - /// codepage when reading a zipfile, you will get entries with filenames that - /// are incorrect, and the incorrect filenames may even contain characters - /// that are not legal for use within filenames in Windows. Extracting entries - /// with illegal characters in the filenames will lead to exceptions. It's too - /// bad, but this is just the way things are with code pages in zip - /// files. Caveat Emptor. - /// - /// - /// - /// Example: Suppose you create a zipfile that contains entries with - /// filenames that have Danish characters. If you use equal to "iso-8859-1" (cp 28591), - /// the filenames will be correctly encoded in the zip. But, to read that - /// zipfile correctly, you have to specify the same codepage at the time you - /// read it. If try to read that zip file with Windows Explorer or another - /// application that is not flexible with respect to the codepage used to - /// decode filenames in zipfiles, you will get a filename like "Inf?txt". - /// - /// - /// - /// When using DotNetZip to read a zip archive, and the zip archive uses an - /// arbitrary code page, you must specify the encoding to use before or when - /// the Zipfile is READ. This means you must use a ZipFile.Read() - /// method that allows you to specify a System.Text.Encoding parameter. Setting - /// the ProvisionalAlternateEncoding property after your application has read in - /// the zip archive will not affect the entry names of entries that have already - /// been read in. - /// - /// - /// - /// And now, the exception to the rule described above. One strategy for - /// specifying the code page for a given zip file is to describe the code page - /// in a human-readable form in the Zip comment. For example, the comment may - /// read "Entries in this archive are encoded in the Big5 code page". For - /// maximum interoperability, the zip comment in this case should be encoded - /// in the default, IBM437 code page. In this case, the zip comment is - /// encoded using a different page than the filenames. To do this, Specify - /// ProvisionalAlternateEncoding to your desired region-specific code - /// page, once before adding any entries, and then reset - /// ProvisionalAlternateEncoding to IBM437 before setting the property and calling Save(). - /// - /// - /// - /// - /// This example shows how to read a zip file using the Big-5 Chinese code page - /// (950), and extract each entry in the zip file. For this code to work as - /// desired, the Zipfile must have been created using the big5 code page - /// (CP950). This is typical, for example, when using WinRar on a machine with - /// CP950 set as the default code page. In that case, the names of entries - /// within the Zip archive will be stored in that code page, and reading the zip - /// archive must be done using that code page. If the application did not use - /// the correct code page in ZipFile.Read(), then names of entries within the - /// zip archive would not be correctly retrieved. - /// - /// using (var zip = ZipFile.Read(zipFileName, System.Text.Encoding.GetEncoding("big5"))) - /// { - /// // retrieve and extract an entry using a name encoded with CP950 - /// zip[MyDesiredEntry].Extract("unpack"); - /// } - /// - /// - /// - /// Using zip As ZipFile = ZipFile.Read(ZipToExtract, System.Text.Encoding.GetEncoding("big5")) - /// ' retrieve and extract an entry using a name encoded with CP950 - /// zip(MyDesiredEntry).Extract("unpack") - /// End Using - /// - /// - /// - /// DefaultEncoding - [Obsolete("use AlternateEncoding instead.")] - public System.Text.Encoding ProvisionalAlternateEncoding - { - get - { - if (_alternateEncodingUsage == ZipOption.AsNecessary) - return _alternateEncoding; - return null; - } - set - { - _alternateEncoding = value; - _alternateEncodingUsage = ZipOption.AsNecessary; - } - } - - - /// - /// A Text Encoding to use when encoding the filenames and comments for - /// all the ZipEntry items, during a ZipFile.Save() operation. - /// - /// - /// - /// Whether the encoding specified here is used during the save depends - /// on . - /// - /// - public System.Text.Encoding AlternateEncoding - { - get - { - return _alternateEncoding; - } - set - { - _alternateEncoding = value; - } - } - - - /// - /// A flag that tells if and when this instance should apply - /// AlternateEncoding to encode the filenames and comments associated to - /// of ZipEntry objects contained within this instance. - /// - public ZipOption AlternateEncodingUsage - { - get - { - return _alternateEncodingUsage; - } - set - { - _alternateEncodingUsage = value; - } - } - - - /// - /// The default text encoding used in zip archives. It is numeric 437, also - /// known as IBM437. - /// - /// - public static System.Text.Encoding DefaultEncoding - { - get - { - return _defaultEncoding; - } - } - - - /// - /// Gets or sets the TextWriter to which status messages are delivered - /// for the instance. - /// - /// - /// - /// If the TextWriter is set to a non-null value, then verbose output is sent - /// to the TextWriter during Add, Read, Save and - /// Extract operations. Typically, console applications might use - /// Console.Out and graphical or headless applications might use a - /// System.IO.StringWriter. The output of this is suitable for viewing - /// by humans. - /// - /// - /// - /// - /// In this example, a console application instantiates a ZipFile, then - /// sets the StatusMessageTextWriter to Console.Out. At that - /// point, all verbose status messages for that ZipFile are sent to the - /// console. - /// - /// - /// - /// using (ZipFile zip= ZipFile.Read(FilePath)) - /// { - /// zip.StatusMessageTextWriter= System.Console.Out; - /// // messages are sent to the console during extraction - /// zip.ExtractAll(); - /// } - /// - /// - /// - /// Using zip As ZipFile = ZipFile.Read(FilePath) - /// zip.StatusMessageTextWriter= System.Console.Out - /// 'Status Messages will be sent to the console during extraction - /// zip.ExtractAll() - /// End Using - /// - /// - /// - /// In this example, a Windows Forms application instantiates a - /// ZipFile, then sets the StatusMessageTextWriter to a - /// StringWriter. At that point, all verbose status messages for that - /// ZipFile are sent to the StringWriter. - /// - /// - /// - /// var sw = new System.IO.StringWriter(); - /// using (ZipFile zip= ZipFile.Read(FilePath)) - /// { - /// zip.StatusMessageTextWriter= sw; - /// zip.ExtractAll(); - /// } - /// Console.WriteLine("{0}", sw.ToString()); - /// - /// - /// - /// Dim sw as New System.IO.StringWriter - /// Using zip As ZipFile = ZipFile.Read(FilePath) - /// zip.StatusMessageTextWriter= sw - /// zip.ExtractAll() - /// End Using - /// 'Status Messages are now available in sw - /// - /// - /// - public TextWriter StatusMessageTextWriter - { - get { return _StatusMessageTextWriter; } - set { _StatusMessageTextWriter = value; } - } - - - - - /// - /// Gets or sets the name for the folder to store the temporary file - /// this library writes when saving a zip archive. - /// - /// - /// - /// - /// This library will create a temporary file when saving a Zip archive to a - /// file. This file is written when calling one of the Save() methods - /// that does not save to a stream, or one of the SaveSelfExtractor() - /// methods. - /// - /// - /// - /// By default, the library will create the temporary file in the directory - /// specified for the file itself, via the property or via - /// the method. - /// - /// - /// - /// Setting this property allows applications to override this default - /// behavior, so that the library will create the temporary file in the - /// specified folder. For example, to have the library create the temporary - /// file in the current working directory, regardless where the ZipFile - /// is saved, specfy ".". To revert to the default behavior, set this - /// property to null (Nothing in VB). - /// - /// - /// - /// When setting the property to a non-null value, the folder specified must - /// exist; if it does not an exception is thrown. The application should have - /// write and delete permissions on the folder. The permissions are not - /// explicitly checked ahead of time; if the application does not have the - /// appropriate rights, an exception will be thrown at the time Save() - /// is called. - /// - /// - /// - /// There is no temporary file created when reading a zip archive. When - /// saving to a Stream, there is no temporary file created. For example, if - /// the application is an ASP.NET application and calls Save() - /// specifying the Response.OutputStream as the output stream, there is - /// no temporary file created. - /// - /// - /// - /// - /// Thrown when setting the property if the directory does not exist. - /// - /// - public String TempFileFolder - { - get { return _TempFileFolder; } - - set - { - _TempFileFolder = value; - if (value == null) return; - - if (!Directory.Exists(value)) - throw new FileNotFoundException(String.Format("That directory ({0}) does not exist.", value)); - - } - } - - /// - /// Sets the password to be used on the ZipFile instance. - /// - /// - /// - /// - /// - /// When writing a zip archive, this password is applied to the entries, not - /// to the zip archive itself. It applies to any ZipEntry subsequently - /// added to the ZipFile, using one of the AddFile, - /// AddDirectory, AddEntry, or AddItem methods, etc. - /// When reading a zip archive, this property applies to any entry - /// subsequently extracted from the ZipFile using one of the Extract - /// methods on the ZipFile class. - /// - /// - /// - /// When writing a zip archive, keep this in mind: though the password is set - /// on the ZipFile object, according to the Zip spec, the "directory" of the - /// archive - in other words the list of entries or files contained in the archive - is - /// not encrypted with the password, or protected in any way. If you set the - /// Password property, the password actually applies to individual entries - /// that are added to the archive, subsequent to the setting of this property. - /// The list of filenames in the archive that is eventually created will - /// appear in clear text, but the contents of the individual files are - /// encrypted. This is how Zip encryption works. - /// - /// - /// - /// One simple way around this limitation is to simply double-wrap sensitive - /// filenames: Store the files in a zip file, and then store that zip file - /// within a second, "outer" zip file. If you apply a password to the outer - /// zip file, then readers will be able to see that the outer zip file - /// contains an inner zip file. But readers will not be able to read the - /// directory or file list of the inner zip file. - /// - /// - /// - /// If you set the password on the ZipFile, and then add a set of files - /// to the archive, then each entry is encrypted with that password. You may - /// also want to change the password between adding different entries. If you - /// set the password, add an entry, then set the password to null - /// (Nothing in VB), and add another entry, the first entry is - /// encrypted and the second is not. If you call AddFile(), then set - /// the Password property, then call ZipFile.Save, the file - /// added will not be password-protected, and no warning will be generated. - /// - /// - /// - /// When setting the Password, you may also want to explicitly set the property, to specify how to encrypt the entries added - /// to the ZipFile. If you set the Password to a non-null value and do not - /// set , then PKZip 2.0 ("Weak") encryption is used. - /// This encryption is relatively weak but is very interoperable. If you set - /// the password to a null value (Nothing in VB), Encryption is - /// reset to None. - /// - /// - /// - /// All of the preceding applies to writing zip archives, in other words when - /// you use one of the Save methods. To use this property when reading or an - /// existing ZipFile, do the following: set the Password property on the - /// ZipFile, then call one of the Extract() overloads on the . In this case, the entry is extracted using the - /// Password that is specified on the ZipFile instance. If you - /// have not set the Password property, then the password is - /// null, and the entry is extracted with no password. - /// - /// - /// - /// If you set the Password property on the ZipFile, then call - /// Extract() an entry that has not been encrypted with a password, the - /// password is not used for that entry, and the ZipEntry is extracted - /// as normal. In other words, the password is used only if necessary. - /// - /// - /// - /// The class also has a Password property. It takes precedence - /// over this property on the ZipFile. Typically, you would use the - /// per-entry Password when most entries in the zip archive use one password, - /// and a few entries use a different password. If all entries in the zip - /// file use the same password, then it is simpler to just set this property - /// on the ZipFile itself, whether creating a zip archive or extracting - /// a zip archive. - /// - /// - /// - /// - /// - /// - /// This example creates a zip file, using password protection for the - /// entries, and then extracts the entries from the zip file. When creating - /// the zip file, the Readme.txt file is not protected with a password, but - /// the other two are password-protected as they are saved. During extraction, - /// each file is extracted with the appropriate password. - /// - /// - /// // create a file with encryption - /// using (ZipFile zip = new ZipFile()) - /// { - /// zip.AddFile("ReadMe.txt"); - /// zip.Password= "!Secret1"; - /// zip.AddFile("MapToTheSite-7440-N49th.png"); - /// zip.AddFile("2008-Regional-Sales-Report.pdf"); - /// zip.Save("EncryptedArchive.zip"); - /// } - /// - /// // extract entries that use encryption - /// using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip")) - /// { - /// zip.Password= "!Secret1"; - /// zip.ExtractAll("extractDir"); - /// } - /// - /// - /// - /// - /// Using zip As New ZipFile - /// zip.AddFile("ReadMe.txt") - /// zip.Password = "123456!" - /// zip.AddFile("MapToTheSite-7440-N49th.png") - /// zip.Password= "!Secret1"; - /// zip.AddFile("2008-Regional-Sales-Report.pdf") - /// zip.Save("EncryptedArchive.zip") - /// End Using - /// - /// - /// ' extract entries that use encryption - /// Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip")) - /// zip.Password= "!Secret1" - /// zip.ExtractAll("extractDir") - /// End Using - /// - /// - /// - /// - /// - /// ZipFile.Encryption - /// ZipEntry.Password - public String Password - { - set - { - _Password = value; - if (_Password == null) - { - Encryption = EncryptionAlgorithm.None; - } - else if (Encryption == EncryptionAlgorithm.None) - { - Encryption = EncryptionAlgorithm.PkzipWeak; - } - } - private get - { - return _Password; - } - } - - - - - - /// - /// The action the library should take when extracting a file that already - /// exists. - /// - /// - /// - /// - /// This property affects the behavior of the Extract methods (one of the - /// Extract() or ExtractWithPassword() overloads), when - /// extraction would would overwrite an existing filesystem file. If you do - /// not set this property, the library throws an exception when extracting an - /// entry would overwrite an existing file. - /// - /// - /// - /// This property has no effect when extracting to a stream, or when the file - /// to be extracted does not already exist. - /// - /// - /// - public ExtractExistingFileAction ExtractExistingFile - { - get; - set; - } - - - /// - /// The action the library should take when an error is encountered while - /// opening or reading files as they are saved into a zip archive. - /// - /// - /// - /// - /// Errors can occur as a file is being saved to the zip archive. For - /// example, the File.Open may fail, or a File.Read may fail, because of - /// lock conflicts or other reasons. - /// - /// - /// - /// The first problem might occur after having called AddDirectory() on a - /// directory that contains a Clipper .dbf file; the file is locked by - /// Clipper and cannot be opened for read by another process. An example of - /// the second problem might occur when trying to zip a .pst file that is in - /// use by Microsoft Outlook. Outlook locks a range on the file, which allows - /// other processes to open the file, but not read it in its entirety. - /// - /// - /// - /// This property tells DotNetZip what you would like to do in the case of - /// these errors. The primary options are: ZipErrorAction.Throw to - /// throw an exception (this is the default behavior if you don't set this - /// property); ZipErrorAction.Skip to Skip the file for which there - /// was an error and continue saving; ZipErrorAction.Retry to Retry - /// the entry that caused the problem; or - /// ZipErrorAction.InvokeErrorEvent to invoke an event handler. - /// - /// - /// - /// This property is implicitly set to ZipErrorAction.InvokeErrorEvent - /// if you add a handler to the event. If you set - /// this property to something other than - /// ZipErrorAction.InvokeErrorEvent, then the ZipError - /// event is implicitly cleared. What it means is you can set one or the - /// other (or neither), depending on what you want, but you never need to set - /// both. - /// - /// - /// - /// As with some other properties on the ZipFile class, like , , and , setting this property on a ZipFile - /// instance will cause the specified ZipErrorAction to be used on all - /// items that are subsequently added to the - /// ZipFile instance. If you set this property after you have added - /// items to the ZipFile, but before you have called Save(), - /// those items will not use the specified error handling action. - /// - /// - /// - /// If you want to handle any errors that occur with any entry in the zip - /// file in the same way, then set this property once, before adding any - /// entries to the zip archive. - /// - /// - /// - /// If you set this property to ZipErrorAction.Skip and you'd like to - /// learn which files may have been skipped after a Save(), you can - /// set the on the ZipFile before - /// calling Save(). A message will be emitted into that writer for - /// each skipped file, if any. - /// - /// - /// - /// - /// - /// This example shows how to tell DotNetZip to skip any files for which an - /// error is generated during the Save(). - /// - /// Public Sub SaveZipFile() - /// Dim SourceFolder As String = "fodder" - /// Dim DestFile As String = "eHandler.zip" - /// Dim sw as New StringWriter - /// Using zipArchive As ZipFile = New ZipFile - /// ' Tell DotNetZip to skip any files for which it encounters an error - /// zipArchive.ZipErrorAction = ZipErrorAction.Skip - /// zipArchive.StatusMessageTextWriter = sw - /// zipArchive.AddDirectory(SourceFolder) - /// zipArchive.Save(DestFile) - /// End Using - /// ' examine sw here to see any messages - /// End Sub - /// - /// - /// - /// - /// - /// - - public ZipErrorAction ZipErrorAction - { - get - { - if (ZipError != null) - _zipErrorAction = ZipErrorAction.InvokeErrorEvent; - return _zipErrorAction; - } - set - { - _zipErrorAction = value; - if (_zipErrorAction != ZipErrorAction.InvokeErrorEvent && ZipError != null) - ZipError = null; - } - } - - - /// - /// The Encryption to use for entries added to the ZipFile. - /// - /// - /// - /// - /// Set this when creating a zip archive, or when updating a zip archive. The - /// specified Encryption is applied to the entries subsequently added to the - /// ZipFile instance. Applications do not need to set the - /// Encryption property when reading or extracting a zip archive. - /// - /// - /// - /// If you set this to something other than EncryptionAlgorithm.None, you - /// will also need to set the . - /// - /// - /// - /// As with some other properties on the ZipFile class, like and , setting this - /// property on a ZipFile instance will cause the specified - /// EncryptionAlgorithm to be used on all items - /// that are subsequently added to the ZipFile instance. In other - /// words, if you set this property after you have added items to the - /// ZipFile, but before you have called Save(), those items will - /// not be encrypted or protected with a password in the resulting zip - /// archive. To get a zip archive with encrypted entries, set this property, - /// along with the property, before calling - /// AddFile, AddItem, or AddDirectory (etc.) on the - /// ZipFile instance. - /// - /// - /// - /// If you read a ZipFile, you can modify the Encryption on an - /// encrypted entry, only by setting the Encryption property on the - /// ZipEntry itself. Setting the Encryption property on the - /// ZipFile, once it has been created via a call to - /// ZipFile.Read(), does not affect entries that were previously read. - /// - /// - /// - /// For example, suppose you read a ZipFile, and there is an encrypted - /// entry. Setting the Encryption property on that ZipFile and - /// then calling Save() on the ZipFile does not update the - /// Encryption used for the entries in the archive. Neither is an - /// exception thrown. Instead, what happens during the Save() is that - /// all previously existing entries are copied through to the new zip archive, - /// with whatever encryption and password that was used when originally - /// creating the zip archive. Upon re-reading that archive, to extract - /// entries, applications should use the original password or passwords, if - /// any. - /// - /// - /// - /// Suppose an application reads a ZipFile, and there is an encrypted - /// entry. Setting the Encryption property on that ZipFile and - /// then adding new entries (via AddFile(), AddEntry(), etc) - /// and then calling Save() on the ZipFile does not update the - /// Encryption on any of the entries that had previously been in the - /// ZipFile. The Encryption property applies only to the - /// newly-added entries. - /// - /// - /// - /// - /// - /// - /// This example creates a zip archive that uses encryption, and then extracts - /// entries from the archive. When creating the zip archive, the ReadMe.txt - /// file is zipped without using a password or encryption. The other files - /// use encryption. - /// - /// - /// - /// // Create a zip archive with AES Encryption. - /// using (ZipFile zip = new ZipFile()) - /// { - /// zip.AddFile("ReadMe.txt"); - /// zip.Encryption= EncryptionAlgorithm.WinZipAes256; - /// zip.Password= "Top.Secret.No.Peeking!"; - /// zip.AddFile("7440-N49th.png"); - /// zip.AddFile("2008-Regional-Sales-Report.pdf"); - /// zip.Save("EncryptedArchive.zip"); - /// } - /// - /// // Extract a zip archive that uses AES Encryption. - /// // You do not need to specify the algorithm during extraction. - /// using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip")) - /// { - /// zip.Password= "Top.Secret.No.Peeking!"; - /// zip.ExtractAll("extractDirectory"); - /// } - /// - /// - /// - /// ' Create a zip that uses Encryption. - /// Using zip As New ZipFile() - /// zip.Encryption= EncryptionAlgorithm.WinZipAes256 - /// zip.Password= "Top.Secret.No.Peeking!" - /// zip.AddFile("ReadMe.txt") - /// zip.AddFile("7440-N49th.png") - /// zip.AddFile("2008-Regional-Sales-Report.pdf") - /// zip.Save("EncryptedArchive.zip") - /// End Using - /// - /// ' Extract a zip archive that uses AES Encryption. - /// ' You do not need to specify the algorithm during extraction. - /// Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip")) - /// zip.Password= "Top.Secret.No.Peeking!" - /// zip.ExtractAll("extractDirectory") - /// End Using - /// - /// - /// - /// - /// ZipFile.Password - /// ZipEntry.Encryption - public EncryptionAlgorithm Encryption - { - get - { - return _Encryption; - } - set - { - if (value == EncryptionAlgorithm.Unsupported) - throw new InvalidOperationException("You may not set Encryption to that value."); - _Encryption = value; - } - } - - - - /// - /// A callback that allows the application to specify the compression level - /// to use for entries subsequently added to the zip archive. - /// - /// - /// - /// - /// - /// With this callback, the DotNetZip library allows the application to - /// determine whether compression will be used, at the time of the - /// Save. This may be useful if the application wants to favor - /// speed over size, and wants to defer the decision until the time of - /// Save. - /// - /// - /// - /// Typically applications set the property on - /// the ZipFile or on each ZipEntry to determine the level of - /// compression used. This is done at the time the entry is added to the - /// ZipFile. Setting the property to - /// Ionic.Zlib.CompressionLevel.None means no compression will be used. - /// - /// - /// - /// This callback allows the application to defer the decision on the - /// CompressionLevel to use, until the time of the call to - /// ZipFile.Save(). The callback is invoked once per ZipEntry, - /// at the time the data for the entry is being written out as part of a - /// Save() operation. The application can use whatever criteria it - /// likes in determining the level to return. For example, an application may - /// wish that no .mp3 files should be compressed, because they are already - /// compressed and the extra compression is not worth the CPU time incurred, - /// and so can return None for all .mp3 entries. - /// - /// - /// - /// The library determines whether compression will be attempted for an entry - /// this way: If the entry is a zero length file, or a directory, no - /// compression is used. Otherwise, if this callback is set, it is invoked - /// and the CompressionLevel is set to the return value. If this - /// callback has not been set, then the previously set value for - /// CompressionLevel is used. - /// - /// - /// - public SetCompressionCallback SetCompression - { - get; - set; - } - - - /// - /// The maximum size of an output segment, when saving a split Zip file. - /// - /// - /// - /// Set this to a non-zero value before calling or to specify that the ZipFile should be saved as a - /// split archive, also sometimes called a spanned archive. Some also - /// call them multi-file archives. - /// - /// - /// - /// A split zip archive is saved in a set of discrete filesystem files, - /// rather than in a single file. This is handy when transmitting the - /// archive in email or some other mechanism that has a limit to the size of - /// each file. The first file in a split archive will be named - /// basename.z01, the second will be named basename.z02, and - /// so on. The final file is named basename.zip. According to the zip - /// specification from PKWare, the minimum value is 65536, for a 64k segment - /// size. The maximum number of segments allows in a split archive is 99. - /// - /// - /// - /// The value of this property determines the maximum size of a split - /// segment when writing a split archive. For example, suppose you have a - /// ZipFile that would save to a single file of 200k. If you set the - /// MaxOutputSegmentSize to 65536 before calling Save(), you - /// will get four distinct output files. On the other hand if you set this - /// property to 256k, then you will get a single-file archive for that - /// ZipFile. - /// - /// - /// - /// The size of each split output file will be as large as possible, up to - /// the maximum size set here. The zip specification requires that some data - /// fields in a zip archive may not span a split boundary, and an output - /// segment may be smaller than the maximum if necessary to avoid that - /// problem. Also, obviously the final segment of the archive may be smaller - /// than the maximum segment size. Segments will never be larger than the - /// value set with this property. - /// - /// - /// - /// You can save a split Zip file only when saving to a regular filesystem - /// file. It's not possible to save a split zip file as a self-extracting - /// archive, nor is it possible to save a split zip file to a stream. When - /// saving to a SFX or to a Stream, this property is ignored. - /// - /// - /// - /// About interoperability: Split or spanned zip files produced by DotNetZip - /// can be read by WinZip or PKZip, and vice-versa. Segmented zip files may - /// not be readable by other tools, if those other tools don't support zip - /// spanning or splitting. When in doubt, test. I don't believe Windows - /// Explorer can extract a split archive. - /// - /// - /// - /// This property has no effect when reading a split archive. You can read - /// a split archive in the normal way with DotNetZip. - /// - /// - /// - /// When saving a zip file, if you want a regular zip file rather than a - /// split zip file, don't set this property, or set it to Zero. - /// - /// - /// - /// If you read a split archive, with and - /// then subsequently call ZipFile.Save(), unless you set this - /// property before calling Save(), you will get a normal, - /// single-file archive. - /// - /// - /// - /// - public Int32 MaxOutputSegmentSize - { - get - { - return _maxOutputSegmentSize; - } - set - { - if (value < 65536 && value != 0) - throw new ZipException("The minimum acceptable segment size is 65536."); - _maxOutputSegmentSize = value; - } - } - - - /// - /// Returns the number of segments used in the most recent Save() operation. - /// - /// - /// - /// This is normally zero, unless you have set the property. If you have set , and then you save a file, after the call to - /// Save() completes, you can read this value to learn the number of segments that - /// were created. - /// - /// - /// If you call Save("Archive.zip"), and it creates 5 segments, then you - /// will have filesystem files named Archive.z01, Archive.z02, Archive.z03, - /// Archive.z04, and Archive.zip, and the value of this property will be 5. - /// - /// - /// - public Int32 NumberOfSegmentsForMostRecentSave - { - get - { - return unchecked((Int32)_numberOfSegmentsForMostRecentSave + 1); - } - } - - -#if !NETCF - /// - /// The size threshold for an entry, above which a parallel deflate is used. - /// - /// - /// - /// - /// - /// DotNetZip will use multiple threads to compress any ZipEntry, - /// if the entry is larger than the given size. Zero means "always - /// use parallel deflate", while -1 means "never use parallel - /// deflate". The default value for this property is 512k. Aside - /// from the special values of 0 and 1, the minimum value is 65536. - /// - /// - /// - /// If the entry size cannot be known before compression, as with a - /// read-forward stream, then Parallel deflate will never be - /// performed, unless the value of this property is zero. - /// - /// - /// - /// A parallel deflate operations will speed up the compression of - /// large files, on computers with multiple CPUs or multiple CPU - /// cores. For files above 1mb, on a dual core or dual-cpu (2p) - /// machine, the time required to compress the file can be 70% of the - /// single-threaded deflate. For very large files on 4p machines the - /// compression can be done in 30% of the normal time. The downside - /// is that parallel deflate consumes extra memory during the deflate, - /// and the deflation is not as effective. - /// - /// - /// - /// Parallel deflate tends to yield slightly less compression when - /// compared to as single-threaded deflate; this is because the original - /// data stream is split into multiple independent buffers, each of which - /// is compressed in parallel. But because they are treated - /// independently, there is no opportunity to share compression - /// dictionaries. For that reason, a deflated stream may be slightly - /// larger when compressed using parallel deflate, as compared to a - /// traditional single-threaded deflate. Sometimes the increase over the - /// normal deflate is as much as 5% of the total compressed size. For - /// larger files it can be as small as 0.1%. - /// - /// - /// - /// Multi-threaded compression does not give as much an advantage when - /// using Encryption. This is primarily because encryption tends to slow - /// down the entire pipeline. Also, multi-threaded compression gives less - /// of an advantage when using lower compression levels, for example . You may have to - /// perform some tests to determine the best approach for your situation. - /// - /// - /// - /// - /// - /// - public long ParallelDeflateThreshold - { - set - { - if ((value != 0) && (value != -1) && (value < 64 * 1024)) - throw new ArgumentOutOfRangeException("ParallelDeflateThreshold should be -1, 0, or > 65536"); - _ParallelDeflateThreshold = value; - } - get - { - return _ParallelDeflateThreshold; - } - } - - /// - /// The maximum number of buffer pairs to use when performing - /// parallel compression. - /// - /// - /// - /// - /// This property sets an upper limit on the number of memory - /// buffer pairs to create when performing parallel - /// compression. The implementation of the parallel - /// compression stream allocates multiple buffers to - /// facilitate parallel compression. As each buffer fills up, - /// the stream uses - /// ThreadPool.QueueUserWorkItem() to compress those - /// buffers in a background threadpool thread. After a buffer - /// is compressed, it is re-ordered and written to the output - /// stream. - /// - /// - /// - /// A higher number of buffer pairs enables a higher degree of - /// parallelism, which tends to increase the speed of compression on - /// multi-cpu computers. On the other hand, a higher number of buffer - /// pairs also implies a larger memory consumption, more active worker - /// threads, and a higher cpu utilization for any compression. This - /// property enables the application to limit its memory consumption and - /// CPU utilization behavior depending on requirements. - /// - /// - /// - /// For each compression "task" that occurs in parallel, there are 2 - /// buffers allocated: one for input and one for output. This property - /// sets a limit for the number of pairs. The total amount of storage - /// space allocated for buffering will then be (N*S*2), where N is the - /// number of buffer pairs, S is the size of each buffer (). By default, DotNetZip allocates 4 buffer - /// pairs per CPU core, so if your machine has 4 cores, and you retain - /// the default buffer size of 128k, then the - /// ParallelDeflateOutputStream will use 4 * 4 * 2 * 128kb of buffer - /// memory in total, or 4mb, in blocks of 128kb. If you then set this - /// property to 8, then the number will be 8 * 2 * 128kb of buffer - /// memory, or 2mb. - /// - /// - /// - /// CPU utilization will also go up with additional buffers, because a - /// larger number of buffer pairs allows a larger number of background - /// threads to compress in parallel. If you find that parallel - /// compression is consuming too much memory or CPU, you can adjust this - /// value downward. - /// - /// - /// - /// The default value is 16. Different values may deliver better or - /// worse results, depending on your priorities and the dynamic - /// performance characteristics of your storage and compute resources. - /// - /// - /// - /// This property is not the number of buffer pairs to use; it is an - /// upper limit. An illustration: Suppose you have an application that - /// uses the default value of this property (which is 16), and it runs - /// on a machine with 2 CPU cores. In that case, DotNetZip will allocate - /// 4 buffer pairs per CPU core, for a total of 8 pairs. The upper - /// limit specified by this property has no effect. - /// - /// - /// - /// The application can set this value at any time - /// before calling ZipFile.Save(). - /// - /// - /// - /// - /// - public int ParallelDeflateMaxBufferPairs - { - get - { - return _maxBufferPairs; - } - set - { - if (value < 4) - throw new ArgumentOutOfRangeException("ParallelDeflateMaxBufferPairs", - "Value must be 4 or greater."); - _maxBufferPairs = value; - } - } -#endif - - - /// Provides a string representation of the instance. - /// a string representation of the instance. - public override String ToString() - { - return String.Format("ZipFile::{0}", Name); - } - - - /// - /// Returns the version number on the DotNetZip assembly. - /// - /// - /// - /// - /// This property is exposed as a convenience. Callers could also get the - /// version value by retrieving GetName().Version on the - /// System.Reflection.Assembly object pointing to the DotNetZip - /// assembly. But sometimes it is not clear which assembly is being loaded. - /// This property makes it clear. - /// - /// - /// This static property is primarily useful for diagnostic purposes. - /// - /// - public static System.Version LibraryVersion - { - get - { - return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version; - } - } - - internal void NotifyEntryChanged() - { - _contentsChanged = true; - } - - - internal Stream StreamForDiskNumber(uint diskNumber) - { - if (diskNumber + 1 == this._diskNumberWithCd || - (diskNumber == 0 && this._diskNumberWithCd == 0)) - { - //return (this.ReadStream as FileStream); - return this.ReadStream; - } - return ZipSegmentedStream.ForReading(this._readName ?? this._name, - diskNumber, _diskNumberWithCd); - } - - - - // called by ZipEntry in ZipEntry.Extract(), when there is no stream set for the - // ZipEntry. - internal void Reset(bool whileSaving) - { - if (_JustSaved) - { - // read in the just-saved zip archive - using (ZipFile x = new ZipFile()) - { - // workitem 10735 - x._readName = x._name = whileSaving - ? (this._readName ?? this._name) - : this._name; - x.AlternateEncoding = this.AlternateEncoding; - x.AlternateEncodingUsage = this.AlternateEncodingUsage; - ReadIntoInstance(x); - // copy the contents of the entries. - // cannot just replace the entries - the app may be holding them - foreach (ZipEntry e1 in x) - { - foreach (ZipEntry e2 in this) - { - if (e1.FileName == e2.FileName) - { - e2.CopyMetaData(e1); - break; - } - } - } - } - _JustSaved = false; - } - } - - - #endregion - - #region Constructors - - /// - /// Creates a new ZipFile instance, using the specified filename. - /// - /// - /// - /// - /// Applications can use this constructor to create a new ZipFile for writing, - /// or to slurp in an existing zip archive for read and update purposes. - /// - /// - /// - /// To create a new zip archive, an application can call this constructor, - /// passing the name of a file that does not exist. The name may be a fully - /// qualified path. Then the application can add directories or files to the - /// ZipFile via AddDirectory(), AddFile(), AddItem() - /// and then write the zip archive to the disk by calling Save(). The - /// zip file is not actually opened and written to the disk until the - /// application calls ZipFile.Save(). At that point the new zip file - /// with the given name is created. - /// - /// - /// - /// If you won't know the name of the Zipfile until the time you call - /// ZipFile.Save(), or if you plan to save to a stream (which has no - /// name), then you should use the no-argument constructor. - /// - /// - /// - /// The application can also call this constructor to read an existing zip - /// archive. passing the name of a valid zip file that does exist. But, it's - /// better form to use the static method, - /// passing the name of the zip file, because using ZipFile.Read() in - /// your code communicates very clearly what you are doing. In either case, - /// the file is then read into the ZipFile instance. The app can then - /// enumerate the entries or can modify the zip file, for example adding - /// entries, removing entries, changing comments, and so on. - /// - /// - /// - /// One advantage to this parameterized constructor: it allows applications to - /// use the same code to add items to a zip archive, regardless of whether the - /// zip file exists. - /// - /// - /// - /// Instances of the ZipFile class are not multi-thread safe. You may - /// not party on a single instance with multiple threads. You may have - /// multiple threads that each use a distinct ZipFile instance, or you - /// can synchronize multi-thread access to a single instance. - /// - /// - /// - /// By the way, since DotNetZip is so easy to use, don't you think you should - /// donate $5 or $10? - /// - /// - /// - /// - /// - /// Thrown if name refers to an existing file that is not a valid zip file. - /// - /// - /// - /// This example shows how to create a zipfile, and add a few files into it. - /// - /// String ZipFileToCreate = "archive1.zip"; - /// String DirectoryToZip = "c:\\reports"; - /// using (ZipFile zip = new ZipFile()) - /// { - /// // Store all files found in the top level directory, into the zip archive. - /// String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip); - /// zip.AddFiles(filenames, "files"); - /// zip.Save(ZipFileToCreate); - /// } - /// - /// - /// - /// Dim ZipFileToCreate As String = "archive1.zip" - /// Dim DirectoryToZip As String = "c:\reports" - /// Using zip As ZipFile = New ZipFile() - /// Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip) - /// zip.AddFiles(filenames, "files") - /// zip.Save(ZipFileToCreate) - /// End Using - /// - /// - /// - /// The filename to use for the new zip archive. - /// - public ZipFile(string fileName) - { - try - { - _InitInstance(fileName, null); - } - catch (Exception e1) - { - throw new ZipException(String.Format("Could not read {0} as a zip file", fileName), e1); - } - } - - - /// - /// Creates a new ZipFile instance, using the specified name for the - /// filename, and the specified Encoding. - /// - /// - /// - /// - /// See the documentation on the ZipFile - /// constructor that accepts a single string argument for basic - /// information on all the ZipFile constructors. - /// - /// - /// - /// The Encoding is used as the default alternate encoding for entries with - /// filenames or comments that cannot be encoded with the IBM437 code page. - /// This is equivalent to setting the property on the ZipFile - /// instance after construction. - /// - /// - /// - /// Instances of the ZipFile class are not multi-thread safe. You may - /// not party on a single instance with multiple threads. You may have - /// multiple threads that each use a distinct ZipFile instance, or you - /// can synchronize multi-thread access to a single instance. - /// - /// - /// - /// - /// - /// Thrown if name refers to an existing file that is not a valid zip file. - /// - /// - /// The filename to use for the new zip archive. - /// The Encoding is used as the default alternate - /// encoding for entries with filenames or comments that cannot be encoded - /// with the IBM437 code page. - public ZipFile(string fileName, System.Text.Encoding encoding) - { - try - { - AlternateEncoding = encoding; - AlternateEncodingUsage = ZipOption.Always; - _InitInstance(fileName, null); - } - catch (Exception e1) - { - throw new ZipException(String.Format("{0} is not a valid zip file", fileName), e1); - } - } - - - - /// - /// Create a zip file, without specifying a target filename or stream to save to. - /// - /// - /// - /// - /// See the documentation on the ZipFile - /// constructor that accepts a single string argument for basic - /// information on all the ZipFile constructors. - /// - /// - /// - /// After instantiating with this constructor and adding entries to the - /// archive, the application should call or - /// to save to a file or a - /// stream, respectively. The application can also set the - /// property and then call the no-argument method. (This - /// is the preferred approach for applications that use the library through - /// COM interop.) If you call the no-argument method - /// without having set the Name of the ZipFile, either through - /// the parameterized constructor or through the explicit property , the - /// Save() will throw, because there is no place to save the file. - /// - /// - /// Instances of the ZipFile class are not multi-thread safe. You may - /// have multiple threads that each use a distinct ZipFile instance, or - /// you can synchronize multi-thread access to a single instance. - /// - /// - /// - /// - /// This example creates a Zip archive called Backup.zip, containing all the files - /// in the directory DirectoryToZip. Files within subdirectories are not zipped up. - /// - /// using (ZipFile zip = new ZipFile()) - /// { - /// // Store all files found in the top level directory, into the zip archive. - /// // note: this code does not recurse subdirectories! - /// String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip); - /// zip.AddFiles(filenames, "files"); - /// zip.Save("Backup.zip"); - /// } - /// - /// - /// - /// Using zip As New ZipFile - /// ' Store all files found in the top level directory, into the zip archive. - /// ' note: this code does not recurse subdirectories! - /// Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip) - /// zip.AddFiles(filenames, "files") - /// zip.Save("Backup.zip") - /// End Using - /// - /// - public ZipFile() - { - _InitInstance(null, null); - } - - - /// - /// Create a zip file, specifying a text Encoding, but without specifying a - /// target filename or stream to save to. - /// - /// - /// - /// - /// See the documentation on the ZipFile - /// constructor that accepts a single string argument for basic - /// information on all the ZipFile constructors. - /// - /// - /// - /// - /// - /// The Encoding is used as the default alternate encoding for entries with - /// filenames or comments that cannot be encoded with the IBM437 code page. - /// - public ZipFile(System.Text.Encoding encoding) - { - AlternateEncoding = encoding; - AlternateEncodingUsage = ZipOption.Always; - _InitInstance(null, null); - } - - - /// - /// Creates a new ZipFile instance, using the specified name for the - /// filename, and the specified status message writer. - /// - /// - /// - /// - /// See the documentation on the ZipFile - /// constructor that accepts a single string argument for basic - /// information on all the ZipFile constructors. - /// - /// - /// - /// This version of the constructor allows the caller to pass in a TextWriter, - /// to which verbose messages will be written during extraction or creation of - /// the zip archive. A console application may wish to pass - /// System.Console.Out to get messages on the Console. A graphical or headless - /// application may wish to capture the messages in a different - /// TextWriter, for example, a StringWriter, and then display - /// the messages in a TextBox, or generate an audit log of ZipFile operations. - /// - /// - /// - /// To encrypt the data for the files added to the ZipFile instance, - /// set the Password property after creating the ZipFile instance. - /// - /// - /// - /// Instances of the ZipFile class are not multi-thread safe. You may - /// not party on a single instance with multiple threads. You may have - /// multiple threads that each use a distinct ZipFile instance, or you - /// can synchronize multi-thread access to a single instance. - /// - /// - /// - /// - /// - /// Thrown if name refers to an existing file that is not a valid zip file. - /// - /// - /// - /// - /// using (ZipFile zip = new ZipFile("Backup.zip", Console.Out)) - /// { - /// // Store all files found in the top level directory, into the zip archive. - /// // note: this code does not recurse subdirectories! - /// // Status messages will be written to Console.Out - /// String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip); - /// zip.AddFiles(filenames); - /// zip.Save(); - /// } - /// - /// - /// - /// Using zip As New ZipFile("Backup.zip", Console.Out) - /// ' Store all files found in the top level directory, into the zip archive. - /// ' note: this code does not recurse subdirectories! - /// ' Status messages will be written to Console.Out - /// Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip) - /// zip.AddFiles(filenames) - /// zip.Save() - /// End Using - /// - /// - /// - /// The filename to use for the new zip archive. - /// A TextWriter to use for writing - /// verbose status messages. - public ZipFile(string fileName, TextWriter statusMessageWriter) - { - try - { - _InitInstance(fileName, statusMessageWriter); - } - catch (Exception e1) - { - throw new ZipException(String.Format("{0} is not a valid zip file", fileName), e1); - } - } - - - /// - /// Creates a new ZipFile instance, using the specified name for the - /// filename, the specified status message writer, and the specified Encoding. - /// - /// - /// - /// - /// This constructor works like the ZipFile - /// constructor that accepts a single string argument. See that - /// reference for detail on what this constructor does. - /// - /// - /// - /// This version of the constructor allows the caller to pass in a - /// TextWriter, and an Encoding. The TextWriter will collect - /// verbose messages that are generated by the library during extraction or - /// creation of the zip archive. A console application may wish to pass - /// System.Console.Out to get messages on the Console. A graphical or - /// headless application may wish to capture the messages in a different - /// TextWriter, for example, a StringWriter, and then display - /// the messages in a TextBox, or generate an audit log of - /// ZipFile operations. - /// - /// - /// - /// The Encoding is used as the default alternate encoding for entries - /// with filenames or comments that cannot be encoded with the IBM437 code - /// page. This is a equivalent to setting the property on the ZipFile - /// instance after construction. - /// - /// - /// - /// To encrypt the data for the files added to the ZipFile instance, - /// set the Password property after creating the ZipFile - /// instance. - /// - /// - /// - /// Instances of the ZipFile class are not multi-thread safe. You may - /// not party on a single instance with multiple threads. You may have - /// multiple threads that each use a distinct ZipFile instance, or you - /// can synchronize multi-thread access to a single instance. - /// - /// - /// - /// - /// - /// Thrown if fileName refers to an existing file that is not a valid zip file. - /// - /// - /// The filename to use for the new zip archive. - /// A TextWriter to use for writing verbose - /// status messages. - /// - /// The Encoding is used as the default alternate encoding for entries with - /// filenames or comments that cannot be encoded with the IBM437 code page. - /// - public ZipFile(string fileName, TextWriter statusMessageWriter, - System.Text.Encoding encoding) - { - try - { - AlternateEncoding = encoding; - AlternateEncodingUsage = ZipOption.Always; - _InitInstance(fileName, statusMessageWriter); - } - catch (Exception e1) - { - throw new ZipException(String.Format("{0} is not a valid zip file", fileName), e1); - } - } - - - - - /// - /// Initialize a ZipFile instance by reading in a zip file. - /// - /// - /// - /// - /// - /// This method is primarily useful from COM Automation environments, when - /// reading or extracting zip files. In COM, it is not possible to invoke - /// parameterized constructors for a class. A COM Automation application can - /// update a zip file by using the default (no argument) - /// constructor, then calling Initialize() to read the contents - /// of an on-disk zip archive into the ZipFile instance. - /// - /// - /// - /// .NET applications are encouraged to use the ZipFile.Read() methods - /// for better clarity. - /// - /// - /// - /// the name of the existing zip file to read in. - public void Initialize(string fileName) - { - try - { - _InitInstance(fileName, null); - } - catch (Exception e1) - { - throw new ZipException(String.Format("{0} is not a valid zip file", fileName), e1); - } - } - - - - private void _initEntriesDictionary() - { - // workitem 9868 - StringComparer sc = (CaseSensitiveRetrieval) ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase; - _entries = (_entries == null) - ? new Dictionary(sc) - : new Dictionary(_entries, sc); - } - - - private void _InitInstance(string zipFileName, TextWriter statusMessageWriter) - { - // create a new zipfile - _name = zipFileName; - _StatusMessageTextWriter = statusMessageWriter; - _contentsChanged = true; - AddDirectoryWillTraverseReparsePoints = true; // workitem 8617 - CompressionLevel = Ionic.Zlib.CompressionLevel.Default; -#if !NETCF - ParallelDeflateThreshold = 512 * 1024; -#endif - // workitem 7685, 9868 - _initEntriesDictionary(); - - if (File.Exists(_name)) - { - if (FullScan) - ReadIntoInstance_Orig(this); - else - ReadIntoInstance(this); - this._fileAlreadyExists = true; - } - - return; - } - #endregion - - - - #region Indexers and Collections - - private List ZipEntriesAsList - { - get - { - if (_zipEntriesAsList == null) - _zipEntriesAsList = new List(_entries.Values); - return _zipEntriesAsList; - } - } - - /// - /// This is an integer indexer into the Zip archive. - /// - /// - /// - /// - /// This property is read-only. - /// - /// - /// - /// Internally, the ZipEntry instances that belong to the - /// ZipFile are stored in a Dictionary. When you use this - /// indexer the first time, it creates a read-only - /// List<ZipEntry> from the Dictionary.Values Collection. - /// If at any time you modify the set of entries in the ZipFile, - /// either by adding an entry, removing an entry, or renaming an - /// entry, a new List will be created, and the numeric indexes for the - /// remaining entries may be different. - /// - /// - /// - /// This means you cannot rename any ZipEntry from - /// inside an enumeration of the zip file. - /// - /// - /// - /// The index value. - /// - /// - /// - /// - /// - /// The ZipEntry within the Zip archive at the specified index. If the - /// entry does not exist in the archive, this indexer throws. - /// - /// - public ZipEntry this[int ix] - { - // workitem 6402 - get - { - return ZipEntriesAsList[ix]; - } - } - - - /// - /// This is a name-based indexer into the Zip archive. - /// - /// - /// - /// - /// This property is read-only. - /// - /// - /// - /// The property on the ZipFile - /// 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. - /// - /// - /// - /// Regardless of case-sensitivity, it is not always the case that - /// this[value].FileName == value. In other words, the FileName - /// property of the ZipEntry retrieved with this indexer, may or may - /// not be equal to the index value. - /// - /// - /// - /// 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, zip["dir1\\entry1.txt"].FileName == - /// "dir1/entry.txt". - /// - /// - /// - /// 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. - /// - /// - /// - /// - /// - /// This example extracts only the entries in a zip file that are .txt files. - /// - /// using (ZipFile zip = ZipFile.Read("PackedDocuments.zip")) - /// { - /// foreach (string s1 in zip.EntryFilenames) - /// { - /// if (s1.EndsWith(".txt")) - /// zip[s1].Extract("textfiles"); - /// } - /// } - /// - /// - /// 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 - /// - /// - /// - /// - /// - /// Thrown if the caller attempts to assign a non-null value to the indexer. - /// - /// - /// - /// 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 - /// property to change this behavior. The - /// pathname can use forward-slashes or backward slashes. - /// - /// - /// - /// The ZipEntry within the Zip archive, given by the specified - /// filename. If the named entry does not exist in the archive, this indexer - /// returns null (Nothing in VB). - /// - /// - 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; - -#if MESSY - foreach (ZipEntry e in _entries.Values) - { - if (this.CaseSensitiveRetrieval) - { - // check for the file match with a case-sensitive comparison. - if (e.FileName == fileName) return e; - // also check for equivalence - if (fileName.Replace("\\", "/") == e.FileName) return e; - if (e.FileName.Replace("\\", "/") == fileName) return e; - - // check for a difference only in trailing slash - if (e.FileName.EndsWith("/")) - { - var fileNameNoSlash = e.FileName.Trim("/".ToCharArray()); - if (fileNameNoSlash == fileName) return e; - // also check for equivalence - if (fileName.Replace("\\", "/") == fileNameNoSlash) return e; - if (fileNameNoSlash.Replace("\\", "/") == fileName) return e; - } - - } - else - { - // check for the file match in a case-insensitive manner. - if (String.Compare(e.FileName, fileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e; - // also check for equivalence - if (String.Compare(fileName.Replace("\\", "/"), e.FileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e; - if (String.Compare(e.FileName.Replace("\\", "/"), fileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e; - - // check for a difference only in trailing slash - if (e.FileName.EndsWith("/")) - { - var fileNameNoSlash = e.FileName.Trim("/".ToCharArray()); - - if (String.Compare(fileNameNoSlash, fileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e; - // also check for equivalence - if (String.Compare(fileName.Replace("\\", "/"), fileNameNoSlash, StringComparison.CurrentCultureIgnoreCase) == 0) return e; - if (String.Compare(fileNameNoSlash.Replace("\\", "/"), fileName, StringComparison.CurrentCultureIgnoreCase) == 0) return e; - - } - - } - - } - return null; - -#endif - } - } - - - /// - /// The list of filenames for the entries contained within the zip archive. - /// - /// - /// - /// According to the ZIP specification, the names of the entries use forward - /// slashes in pathnames. If you are scanning through the list, you may have - /// to swap forward slashes for backslashes. - /// - /// - /// - /// - /// - /// This example shows one way to test if a filename is already contained - /// within a zip archive. - /// - /// String zipFileToRead= "PackedDocuments.zip"; - /// string candidate = "DatedMaterial.xps"; - /// using (ZipFile zip = new ZipFile(zipFileToRead)) - /// { - /// if (zip.EntryFilenames.Contains(candidate)) - /// Console.WriteLine("The file '{0}' exists in the zip archive '{1}'", - /// candidate, - /// zipFileName); - /// else - /// Console.WriteLine("The file, '{0}', does not exist in the zip archive '{1}'", - /// candidate, - /// zipFileName); - /// Console.WriteLine(); - /// } - /// - /// - /// Dim zipFileToRead As String = "PackedDocuments.zip" - /// Dim candidate As String = "DatedMaterial.xps" - /// Using zip As ZipFile.Read(ZipFileToRead) - /// If zip.EntryFilenames.Contains(candidate) Then - /// Console.WriteLine("The file '{0}' exists in the zip archive '{1}'", _ - /// candidate, _ - /// zipFileName) - /// Else - /// Console.WriteLine("The file, '{0}', does not exist in the zip archive '{1}'", _ - /// candidate, _ - /// zipFileName) - /// End If - /// Console.WriteLine - /// End Using - /// - /// - /// - /// - /// The list of strings for the filenames contained within the Zip archive. - /// - /// - public System.Collections.Generic.ICollection EntryFileNames - { - get - { - return _entries.Keys; - } - } - - - /// - /// Returns the readonly collection of entries in the Zip archive. - /// - /// - /// - /// - /// - /// If there are no entries in the current ZipFile, the value returned is a - /// non-null zero-element collection. If there are entries in the zip file, - /// the elements are returned in no particular order. - /// - /// - /// This is the implied enumerator on the ZipFile class. If you use a - /// ZipFile instance in a context that expects an enumerator, you will - /// get this collection. - /// - /// - /// - public System.Collections.Generic.ICollection Entries - { - get - { - return _entries.Values; - } - } - - - /// - /// Returns a readonly collection of entries in the Zip archive, sorted by FileName. - /// - /// - /// - /// If there are no entries in the current ZipFile, the value returned - /// is a non-null zero-element collection. If there are entries in the zip - /// file, the elements are returned sorted by the name of the entry. - /// - /// - /// - /// - /// This example fills a Windows Forms ListView with the entries in a zip file. - /// - /// - /// using (ZipFile zip = ZipFile.Read(zipFile)) - /// { - /// foreach (ZipEntry entry in zip.EntriesSorted) - /// { - /// ListViewItem item = new ListViewItem(n.ToString()); - /// n++; - /// string[] subitems = new string[] { - /// entry.FileName.Replace("/","\\"), - /// entry.LastModified.ToString("yyyy-MM-dd HH:mm:ss"), - /// entry.UncompressedSize.ToString(), - /// String.Format("{0,5:F0}%", entry.CompressionRatio), - /// entry.CompressedSize.ToString(), - /// (entry.UsesEncryption) ? "Y" : "N", - /// String.Format("{0:X8}", entry.Crc)}; - /// - /// foreach (String s in subitems) - /// { - /// ListViewItem.ListViewSubItem subitem = new ListViewItem.ListViewSubItem(); - /// subitem.Text = s; - /// item.SubItems.Add(subitem); - /// } - /// - /// this.listView1.Items.Add(item); - /// } - /// } - /// - /// - /// - /// - public System.Collections.Generic.ICollection EntriesSorted - { - get - { - var coll = new System.Collections.Generic.List(); - foreach (var e in this.Entries) - { - coll.Add(e); - } - StringComparison sc = (CaseSensitiveRetrieval) ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase; - - coll.Sort((x, y) => { return String.Compare(x.FileName, y.FileName, sc); }); - return coll.AsReadOnly(); - } - } - - - /// - /// Returns the number of entries in the Zip archive. - /// - public int Count - { - get - { - return _entries.Count; - } - } - - - - /// - /// Removes the given ZipEntry from the zip archive. - /// - /// - /// - /// - /// After calling RemoveEntry, the application must call Save to - /// make the changes permanent. - /// - /// - /// - /// - /// Thrown if the specified ZipEntry does not exist in the ZipFile. - /// - /// - /// - /// In this example, all entries in the zip archive dating from before - /// December 31st, 2007, are removed from the archive. This is actually much - /// easier if you use the RemoveSelectedEntries method. But I needed an - /// example for RemoveEntry, so here it is. - /// - /// String ZipFileToRead = "ArchiveToModify.zip"; - /// System.DateTime Threshold = new System.DateTime(2007,12,31); - /// using (ZipFile zip = ZipFile.Read(ZipFileToRead)) - /// { - /// var EntriesToRemove = new System.Collections.Generic.List<ZipEntry>(); - /// foreach (ZipEntry e in zip) - /// { - /// if (e.LastModified < Threshold) - /// { - /// // We cannot remove the entry from the list, within the context of - /// // an enumeration of said list. - /// // So we add the doomed entry to a list to be removed later. - /// EntriesToRemove.Add(e); - /// } - /// } - /// - /// // actually remove the doomed entries. - /// foreach (ZipEntry zombie in EntriesToRemove) - /// zip.RemoveEntry(zombie); - /// - /// zip.Comment= String.Format("This zip archive was updated at {0}.", - /// System.DateTime.Now.ToString("G")); - /// - /// // save with a different name - /// zip.Save("Archive-Updated.zip"); - /// } - /// - /// - /// - /// Dim ZipFileToRead As String = "ArchiveToModify.zip" - /// Dim Threshold As New DateTime(2007, 12, 31) - /// Using zip As ZipFile = ZipFile.Read(ZipFileToRead) - /// Dim EntriesToRemove As New System.Collections.Generic.List(Of ZipEntry) - /// Dim e As ZipEntry - /// For Each e In zip - /// If (e.LastModified < Threshold) Then - /// ' We cannot remove the entry from the list, within the context of - /// ' an enumeration of said list. - /// ' So we add the doomed entry to a list to be removed later. - /// EntriesToRemove.Add(e) - /// End If - /// Next - /// - /// ' actually remove the doomed entries. - /// Dim zombie As ZipEntry - /// For Each zombie In EntriesToRemove - /// zip.RemoveEntry(zombie) - /// Next - /// zip.Comment = String.Format("This zip archive was updated at {0}.", DateTime.Now.ToString("G")) - /// 'save as a different name - /// zip.Save("Archive-Updated.zip") - /// End Using - /// - /// - /// - /// - /// The ZipEntry to remove from the zip. - /// - /// - /// - /// - public void RemoveEntry(ZipEntry entry) - { - //if (!_entries.Values.Contains(entry)) - // throw new ArgumentException("The entry you specified does not exist in the zip archive."); - if (entry == null) - throw new ArgumentNullException("entry"); - - _entries.Remove(SharedUtilities.NormalizePathForUseInZipFile(entry.FileName)); - _zipEntriesAsList = null; - -#if NOTNEEDED - if (_direntries != null) - { - bool FoundAndRemovedDirEntry = false; - foreach (ZipDirEntry de1 in _direntries) - { - if (entry.FileName == de1.FileName) - { - _direntries.Remove(de1); - FoundAndRemovedDirEntry = true; - break; - } - } - - if (!FoundAndRemovedDirEntry) - throw new BadStateException("The entry to be removed was not found in the directory."); - } -#endif - _contentsChanged = true; - } - - - - - /// - /// Removes the ZipEntry with the given filename from the zip archive. - /// - /// - /// - /// - /// After calling RemoveEntry, the application must call Save to - /// make the changes permanent. - /// - /// - /// - /// - /// - /// Thrown if the ZipFile is not updatable. - /// - /// - /// - /// Thrown if a ZipEntry with the specified filename does not exist in - /// the ZipFile. - /// - /// - /// - /// - /// This example shows one way to remove an entry with a given filename from - /// an existing zip archive. - /// - /// - /// String zipFileToRead= "PackedDocuments.zip"; - /// string candidate = "DatedMaterial.xps"; - /// using (ZipFile zip = ZipFile.Read(zipFileToRead)) - /// { - /// if (zip.EntryFilenames.Contains(candidate)) - /// { - /// zip.RemoveEntry(candidate); - /// zip.Comment= String.Format("The file '{0}' has been removed from this archive.", - /// Candidate); - /// zip.Save(); - /// } - /// } - /// - /// - /// Dim zipFileToRead As String = "PackedDocuments.zip" - /// Dim candidate As String = "DatedMaterial.xps" - /// Using zip As ZipFile = ZipFile.Read(zipFileToRead) - /// If zip.EntryFilenames.Contains(candidate) Then - /// zip.RemoveEntry(candidate) - /// zip.Comment = String.Format("The file '{0}' has been removed from this archive.", Candidate) - /// zip.Save - /// End If - /// End Using - /// - /// - /// - /// - /// The name of the file, including any directory path, to remove from the zip. - /// The filename match is not case-sensitive by default; you can use the - /// CaseSensitiveRetrieval property to change this behavior. The - /// pathname can use forward-slashes or backward slashes. - /// - /// - public void RemoveEntry(String fileName) - { - string modifiedName = ZipEntry.NameInArchive(fileName, null); - ZipEntry e = this[modifiedName]; - if (e == null) - throw new ArgumentException("The entry you specified was not found in the zip archive."); - - RemoveEntry(e); - } - - - #endregion - - #region Destructors and Disposers - - // /// - // /// This is the class Destructor, which gets called implicitly when the instance - // /// is destroyed. Because the ZipFile type implements IDisposable, this - // /// method calls Dispose(false). - // /// - // ~ZipFile() - // { - // // call Dispose with false. Since we're in the - // // destructor call, the managed resources will be - // // disposed of anyways. - // Dispose(false); - // } - - /// - /// Closes the read and write streams associated - /// to the ZipFile, if necessary. - /// - /// - /// - /// The Dispose() method is generally employed implicitly, via a using(..) {..} - /// statement. (Using...End Using in VB) If you do not employ a using - /// statement, insure that your application calls Dispose() explicitly. For - /// example, in a Powershell application, or an application that uses the COM - /// interop interface, you must call Dispose() explicitly. - /// - /// - /// - /// This example extracts an entry selected by name, from the Zip file to the - /// Console. - /// - /// using (ZipFile zip = ZipFile.Read(zipfile)) - /// { - /// foreach (ZipEntry e in zip) - /// { - /// if (WantThisEntry(e.FileName)) - /// zip.Extract(e.FileName, Console.OpenStandardOutput()); - /// } - /// } // Dispose() is called implicitly here. - /// - /// - /// - /// Using zip As ZipFile = ZipFile.Read(zipfile) - /// Dim e As ZipEntry - /// For Each e In zip - /// If WantThisEntry(e.FileName) Then - /// zip.Extract(e.FileName, Console.OpenStandardOutput()) - /// End If - /// Next - /// End Using ' Dispose is implicity called here - /// - /// - public void Dispose() - { - // dispose of the managed and unmanaged resources - Dispose(true); - - // tell the GC that the Finalize process no longer needs - // to be run for this object. - GC.SuppressFinalize(this); - } - - /// - /// Disposes any managed resources, if the flag is set, then marks the - /// instance disposed. This method is typically not called explicitly from - /// application code. - /// - /// - /// - /// Applications should call the no-arg Dispose method. - /// - /// - /// - /// indicates whether the method should dispose streams or not. - /// - protected virtual void Dispose(bool disposeManagedResources) - { - if (!this._disposed) - { - if (disposeManagedResources) - { - // dispose managed resources - if (_ReadStreamIsOurs) - { - if (_readstream != null) - { - // workitem 7704 -#if NETCF - _readstream.Close(); -#else - _readstream.Dispose(); -#endif - _readstream = null; - } - } - // only dispose the writestream if there is a backing file - if ((_temporaryFileName != null) && (_name != null)) - if (_writestream != null) - { - // workitem 7704 -#if NETCF - _writestream.Close(); -#else - _writestream.Dispose(); -#endif - _writestream = null; - } - -#if !NETCF - // workitem 10030 - if (this.ParallelDeflater != null) - { - this.ParallelDeflater.Dispose(); - this.ParallelDeflater = null; - } -#endif - } - this._disposed = true; - } - } - #endregion - - - #region private properties - - internal Stream ReadStream - { - get - { - if (_readstream == null) - { - if (_readName != null || _name !=null) - { - _readstream = File.Open(_readName ?? _name, - FileMode.Open, - FileAccess.Read, - FileShare.Read | FileShare.Write); - _ReadStreamIsOurs = true; - } - } - return _readstream; - } - } - - - - private Stream WriteStream - { - // workitem 9763 - get - { - if (_writestream != null) return _writestream; - if (_name == null) return _writestream; - - if (_maxOutputSegmentSize != 0) - { - _writestream = ZipSegmentedStream.ForWriting(this._name, _maxOutputSegmentSize); - return _writestream; - } - - SharedUtilities.CreateAndOpenUniqueTempFile(TempFileFolder ?? Path.GetDirectoryName(_name), - out _writestream, - out _temporaryFileName); - return _writestream; - } - set - { - if (value != null) - throw new ZipException("Cannot set the stream to a non-null value."); - _writestream = null; - } - } - #endregion - - #region private fields - private TextWriter _StatusMessageTextWriter; - private bool _CaseSensitiveRetrieval; - private Stream _readstream; - private Stream _writestream; - private UInt16 _versionMadeBy; - private UInt16 _versionNeededToExtract; - private UInt32 _diskNumberWithCd; - private Int32 _maxOutputSegmentSize; - private UInt32 _numberOfSegmentsForMostRecentSave; - private ZipErrorAction _zipErrorAction; - private bool _disposed; - //private System.Collections.Generic.List _entries; - private System.Collections.Generic.Dictionary _entries; - private List _zipEntriesAsList; - private string _name; - private string _readName; - private string _Comment; - internal string _Password; - private bool _emitNtfsTimes = true; - private bool _emitUnixTimes; - private Ionic.Zlib.CompressionStrategy _Strategy = Ionic.Zlib.CompressionStrategy.Default; - private Ionic.Zip.CompressionMethod _compressionMethod = Ionic.Zip.CompressionMethod.Deflate; - private bool _fileAlreadyExists; - private string _temporaryFileName; - private bool _contentsChanged; - private bool _hasBeenSaved; - private String _TempFileFolder; - private bool _ReadStreamIsOurs = true; - private object LOCK = new object(); - private bool _saveOperationCanceled; - private bool _extractOperationCanceled; - private bool _addOperationCanceled; - private EncryptionAlgorithm _Encryption; - private bool _JustSaved; - private long _locEndOfCDS = -1; - private uint _OffsetOfCentralDirectory; - private Int64 _OffsetOfCentralDirectory64; - private Nullable _OutputUsesZip64; - internal bool _inExtractAll; - private System.Text.Encoding _alternateEncoding = System.Text.Encoding.GetEncoding("IBM437"); // UTF-8 - private ZipOption _alternateEncodingUsage = ZipOption.Never; - private static System.Text.Encoding _defaultEncoding = System.Text.Encoding.GetEncoding("IBM437"); - - private int _BufferSize = BufferSizeDefault; - -#if !NETCF - internal Ionic.Zlib.ParallelDeflateOutputStream ParallelDeflater; - private long _ParallelDeflateThreshold; - private int _maxBufferPairs = 16; -#endif - - internal Zip64Option _zip64 = Zip64Option.Default; -#pragma warning disable 649 - private bool _SavingSfx; -#pragma warning restore 649 - - /// - /// Default size of the buffer used for IO. - /// - public static readonly int BufferSizeDefault = 32768; - - #endregion - } - - /// - /// Options for using ZIP64 extensions when saving zip archives. - /// - /// - /// - /// - /// - /// Designed many years ago, the original zip - /// specification from PKWARE allowed for 32-bit quantities for the - /// compressed and uncompressed sizes of zip entries, as well as a 32-bit quantity - /// for specifying the length of the zip archive itself, and a maximum of 65535 - /// entries. These limits are now regularly exceeded in many backup and archival - /// scenarios. Recently, PKWare added extensions to the original zip spec, called - /// "ZIP64 extensions", to raise those limitations. This property governs whether - /// DotNetZip will use those extensions when writing zip archives. The use of - /// these extensions is optional and explicit in DotNetZip because, despite the - /// status of ZIP64 as a bona fide standard, many other zip tools and libraries do - /// not support ZIP64, and therefore a zip file with ZIP64 extensions may be - /// unreadable by some of those other tools. - /// - /// - /// - /// Set this property to to always use ZIP64 - /// extensions when saving, regardless of whether your zip archive needs it. - /// Suppose you add 5 files, each under 100k, to a ZipFile. If you specify Always - /// for this flag, you will get a ZIP64 archive, though the archive does not need - /// to use ZIP64 because none of the original zip limits had been exceeded. - /// - /// - /// - /// Set this property to to tell the DotNetZip - /// library to never use ZIP64 extensions. This is useful for maximum - /// compatibility and interoperability, at the expense of the capability of - /// handling large files or large archives. NB: Windows Explorer in Windows XP - /// and Windows Vista cannot currently extract files from a zip64 archive, so if - /// you want to guarantee that a zip archive produced by this library will work in - /// Windows Explorer, use Never. If you set this property to , and your application creates a zip that would - /// exceed one of the Zip limits, the library will throw an exception while saving - /// the zip file. - /// - /// - /// - /// Set this property to to tell the - /// DotNetZip library to use the ZIP64 extensions when required by the - /// entry. After the file is compressed, the original and compressed sizes are - /// checked, and if they exceed the limits described above, then zip64 can be - /// used. That is the general idea, but there is an additional wrinkle when saving - /// to a non-seekable device, like the ASP.NET Response.OutputStream, or - /// Console.Out. When using non-seekable streams for output, the entry - /// header - which indicates whether zip64 is in use - is emitted before it is - /// known if zip64 is necessary. It is only after all entries have been saved - /// that it can be known if ZIP64 will be required. On seekable output streams, - /// after saving all entries, the library can seek backward and re-emit the zip - /// file header to be consistent with the actual ZIP64 requirement. But using a - /// non-seekable output stream, the library cannot seek backward, so the header - /// can never be changed. In other words, the archive's use of ZIP64 extensions is - /// not alterable after the header is emitted. Therefore, when saving to - /// non-seekable streams, using is the same - /// as using : it will always produce a zip - /// archive that uses ZIP64 extensions. - /// - /// - /// - public enum Zip64Option - { - /// - /// The default behavior, which is "Never". - /// (For COM clients, this is a 0 (zero).) - /// - Default = 0, - /// - /// Do not use ZIP64 extensions when writing zip archives. - /// (For COM clients, this is a 0 (zero).) - /// - Never = 0, - /// - /// Use ZIP64 extensions when writing zip archives, as necessary. - /// For example, when a single entry exceeds 0xFFFFFFFF in size, or when the archive as a whole - /// exceeds 0xFFFFFFFF in size, or when there are more than 65535 entries in an archive. - /// (For COM clients, this is a 1.) - /// - AsNecessary = 1, - /// - /// Always use ZIP64 extensions when writing zip archives, even when unnecessary. - /// (For COM clients, this is a 2.) - /// - Always - } - - - /// - /// An enum representing the values on a three-way toggle switch - /// for various options in the library. This might be used to - /// specify whether to employ a particular text encoding, or to use - /// ZIP64 extensions, or some other option. - /// - public enum ZipOption - { - /// - /// The default behavior. This is the same as "Never". - /// (For COM clients, this is a 0 (zero).) - /// - Default = 0, - /// - /// Never use the associated option. - /// (For COM clients, this is a 0 (zero).) - /// - Never = 0, - /// - /// Use the associated behavior "as necessary." - /// (For COM clients, this is a 1.) - /// - AsNecessary = 1, - /// - /// Use the associated behavior Always, whether necessary or not. - /// (For COM clients, this is a 2.) - /// - Always - } - - - enum AddOrUpdateAction - { - AddOnly = 0, - AddOrUpdate - } - -} - - - -// ================================================================== -// -// Information on the ZIP format: -// -// From -// http://www.pkware.com/documents/casestudies/APPNOTE.TXT -// -// Overall .ZIP file format: -// -// [local file header 1] -// [file data 1] -// [data descriptor 1] ** sometimes -// . -// . -// . -// [local file header n] -// [file data n] -// [data descriptor n] ** sometimes -// [archive decryption header] -// [archive extra data record] -// [central directory] -// [zip64 end of central directory record] -// [zip64 end of central directory locator] -// [end of central directory record] -// -// Local File Header format: -// local file header signature ... 4 bytes (0x04034b50) -// version needed to extract ..... 2 bytes -// general purpose bit field ..... 2 bytes -// compression method ............ 2 bytes -// last mod file time ............ 2 bytes -// last mod file date............. 2 bytes -// crc-32 ........................ 4 bytes -// compressed size................ 4 bytes -// uncompressed size.............. 4 bytes -// file name length............... 2 bytes -// extra field length ............ 2 bytes -// file name varies -// extra field varies -// -// -// Data descriptor: (used only when bit 3 of the general purpose bitfield is set) -// (although, I have found zip files where bit 3 is not set, yet this descriptor is present!) -// local file header signature 4 bytes (0x08074b50) ** sometimes!!! Not always -// crc-32 4 bytes -// compressed size 4 bytes -// uncompressed size 4 bytes -// -// -// Central directory structure: -// -// [file header 1] -// . -// . -// . -// [file header n] -// [digital signature] -// -// -// File header: (This is a ZipDirEntry) -// central file header signature 4 bytes (0x02014b50) -// version made by 2 bytes -// version needed to extract 2 bytes -// general purpose bit flag 2 bytes -// compression method 2 bytes -// last mod file time 2 bytes -// last mod file date 2 bytes -// crc-32 4 bytes -// compressed size 4 bytes -// uncompressed size 4 bytes -// file name length 2 bytes -// extra field length 2 bytes -// file comment length 2 bytes -// disk number start 2 bytes -// internal file attributes ** 2 bytes -// external file attributes *** 4 bytes -// relative offset of local header 4 bytes -// file name (variable size) -// extra field (variable size) -// file comment (variable size) -// -// ** The internal file attributes, near as I can tell, -// uses 0x01 for a file and a 0x00 for a directory. -// -// ***The external file attributes follows the MS-DOS file attribute byte, described here: -// at http://support.microsoft.com/kb/q125019/ -// 0x0010 => directory -// 0x0020 => file -// -// -// End of central directory record: -// -// end of central dir signature 4 bytes (0x06054b50) -// number of this disk 2 bytes -// number of the disk with the -// start of the central directory 2 bytes -// total number of entries in the -// central directory on this disk 2 bytes -// total number of entries in -// the central directory 2 bytes -// size of the central directory 4 bytes -// offset of start of central -// directory with respect to -// the starting disk number 4 bytes -// .ZIP file comment length 2 bytes -// .ZIP file comment (variable size) -// -// date and time are packed values, as MSDOS did them -// time: bits 0-4 : seconds (divided by 2) -// 5-10: minute -// 11-15: hour -// date bits 0-4 : day -// 5-8: month -// 9-15 year (since 1980) -// -// see http://msdn.microsoft.com/en-us/library/ms724274(VS.85).aspx - diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.x-IEnumerable.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.x-IEnumerable.cs deleted file mode 100644 index b6cd816d..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipFile.x-IEnumerable.cs +++ /dev/null @@ -1,154 +0,0 @@ -// ZipFile.x-IEnumerable.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2006, 2007, 2008, 2009 Dino Chiesa and Microsoft Corporation. -// 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: <2009-December-26 15:13:26> -// -// ------------------------------------------------------------------ -// -// This module defines smoe methods for IEnumerable support. It is -// particularly important for COM to have these things in a separate module. -// -// ------------------------------------------------------------------ - - -namespace Ionic.Zip -{ - - // For some weird reason, the method with the DispId(-4) attribute, which is used as - // the _NewEnum() method, and which is required to get enumeration to work from COM - // environments like VBScript and Javascript (etc) must be the LAST MEMBER in the - // source. In the event of Partial classes, it needs to be the last member defined - // in the last source module. The source modules are ordered alphabetically by - // filename. Not sure why this is true. In any case, we put the enumeration stuff - // here in this oddly-named module, for this reason. - // - - - - public partial class ZipFile - { - - - - - /// - /// Generic IEnumerator support, for use of a ZipFile in an enumeration. - /// - /// - /// - /// You probably do not want to call GetEnumerator explicitly. Instead - /// it is implicitly called when you use a loop in C#, or a - /// For Each loop in VB.NET. - /// - /// - /// - /// This example reads a zipfile of a given name, then enumerates the - /// entries in that zip file, and displays the information about each - /// entry on the Console. - /// - /// using (ZipFile zip = ZipFile.Read(zipfile)) - /// { - /// bool header = true; - /// foreach (ZipEntry e in zip) - /// { - /// if (header) - /// { - /// System.Console.WriteLine("Zipfile: {0}", zip.Name); - /// System.Console.WriteLine("Version Needed: 0x{0:X2}", e.VersionNeeded); - /// System.Console.WriteLine("BitField: 0x{0:X2}", e.BitField); - /// System.Console.WriteLine("Compression Method: 0x{0:X2}", e.CompressionMethod); - /// System.Console.WriteLine("\n{1,-22} {2,-6} {3,4} {4,-8} {0}", - /// "Filename", "Modified", "Size", "Ratio", "Packed"); - /// System.Console.WriteLine(new System.String('-', 72)); - /// header = false; - /// } - /// - /// System.Console.WriteLine("{1,-22} {2,-6} {3,4:F0}% {4,-8} {0}", - /// e.FileName, - /// e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"), - /// e.UncompressedSize, - /// e.CompressionRatio, - /// e.CompressedSize); - /// - /// e.Extract(); - /// } - /// } - /// - /// - /// - /// Dim ZipFileToExtract As String = "c:\foo.zip" - /// Using zip As ZipFile = ZipFile.Read(ZipFileToExtract) - /// Dim header As Boolean = True - /// Dim e As ZipEntry - /// For Each e In zip - /// If header Then - /// Console.WriteLine("Zipfile: {0}", zip.Name) - /// Console.WriteLine("Version Needed: 0x{0:X2}", e.VersionNeeded) - /// Console.WriteLine("BitField: 0x{0:X2}", e.BitField) - /// Console.WriteLine("Compression Method: 0x{0:X2}", e.CompressionMethod) - /// Console.WriteLine(ChrW(10) & "{1,-22} {2,-6} {3,4} {4,-8} {0}", _ - /// "Filename", "Modified", "Size", "Ratio", "Packed" ) - /// Console.WriteLine(New String("-"c, 72)) - /// header = False - /// End If - /// Console.WriteLine("{1,-22} {2,-6} {3,4:F0}% {4,-8} {0}", _ - /// e.FileName, _ - /// e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"), _ - /// e.UncompressedSize, _ - /// e.CompressionRatio, _ - /// e.CompressedSize ) - /// e.Extract - /// Next - /// End Using - /// - /// - /// - /// A generic enumerator suitable for use within a foreach loop. - public System.Collections.Generic.IEnumerator GetEnumerator() - { - foreach (ZipEntry e in _entries.Values) - yield return e; - } - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - - /// - /// An IEnumerator, for use of a ZipFile in a foreach construct. - /// - /// - /// - /// This method is included for COM support. An application generally does not call - /// this method directly. It is called implicitly by COM clients when enumerating - /// the entries in the ZipFile instance. In VBScript, this is done with a For Each - /// statement. In Javascript, this is done with new Enumerator(zipfile). - /// - /// - /// - /// The IEnumerator over the entries in the ZipFile. - /// - [System.Runtime.InteropServices.DispId(-4)] - public System.Collections.IEnumerator GetNewEnum() // the name of this method is not significant - { - return GetEnumerator(); - } - - } -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipInputStream.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipInputStream.cs deleted file mode 100644 index 25622f6c..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipInputStream.cs +++ /dev/null @@ -1,827 +0,0 @@ -// ZipInputStream.cs -// -// ------------------------------------------------------------------ -// -// Copyright (c) 2009-2010 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:48:30> -// -// ------------------------------------------------------------------ -// -// This module defines the ZipInputStream class, which is a stream metaphor for -// reading zip files. This class does not depend on Ionic.Zip.ZipFile, but rather -// stands alongside it as an alternative "container" for ZipEntry, when reading zips. -// -// It adds one interesting method to the normal "stream" interface: GetNextEntry. -// -// ------------------------------------------------------------------ -// - -using System; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using Ionic.Zip; - -namespace Ionic.Zip -{ - /// - /// Provides a stream metaphor for reading zip files. - /// - /// - /// - /// - /// This class provides an alternative programming model for reading zip files to - /// the one enabled by the class. Use this when reading zip - /// files, as an alternative to the class, when you would - /// like to use a Stream class to read the file. - /// - /// - /// - /// Some application designs require a readable stream for input. This stream can - /// be used to read a zip file, and extract entries. - /// - /// - /// - /// Both the ZipInputStream class and the ZipFile class can be used - /// to read and extract zip files. Both of them support many of the common zip - /// features, including Unicode, different compression levels, and ZIP64. The - /// programming models differ. For example, when extracting entries via calls to - /// the GetNextEntry() and Read() methods on the - /// ZipInputStream class, the caller is responsible for creating the file, - /// writing the bytes into the file, setting the attributes on the file, and - /// setting the created, last modified, and last accessed timestamps on the - /// file. All of these things are done automatically by a call to ZipEntry.Extract(). For this reason, the - /// ZipInputStream is generally recommended for when your application wants - /// to extract the data, without storing that data into a file. - /// - /// - /// - /// Aside from the obvious differences in programming model, there are some - /// differences in capability between the ZipFile class and the - /// ZipInputStream class. - /// - /// - /// - /// - /// ZipFile can be used to create or update zip files, or read and - /// extract zip files. ZipInputStream can be used only to read and - /// extract zip files. If you want to use a stream to create zip files, check - /// out the . - /// - /// - /// - /// ZipInputStream cannot read segmented or spanned - /// zip files. - /// - /// - /// - /// ZipInputStream will not read Zip file comments. - /// - /// - /// - /// When reading larger files, ZipInputStream will always underperform - /// ZipFile. This is because the ZipInputStream does a full scan on the - /// zip file, while the ZipFile class reads the central directory of the - /// zip file. - /// - /// - /// - /// - /// - public class ZipInputStream : Stream - { - /// - /// Create a ZipInputStream, wrapping it around an existing stream. - /// - /// - /// - /// - /// - /// While the class is generally easier - /// to use, this class provides an alternative to those - /// applications that want to read from a zipfile directly, - /// using a . - /// - /// - /// - /// Both the ZipInputStream class and the ZipFile class can be used - /// to read and extract zip files. Both of them support many of the common zip - /// features, including Unicode, different compression levels, and ZIP64. The - /// programming models differ. For example, when extracting entries via calls to - /// the GetNextEntry() and Read() methods on the - /// ZipInputStream class, the caller is responsible for creating the file, - /// writing the bytes into the file, setting the attributes on the file, and - /// setting the created, last modified, and last accessed timestamps on the - /// file. All of these things are done automatically by a call to ZipEntry.Extract(). For this reason, the - /// ZipInputStream is generally recommended for when your application wants - /// to extract the data, without storing that data into a file. - /// - /// - /// - /// Aside from the obvious differences in programming model, there are some - /// differences in capability between the ZipFile class and the - /// ZipInputStream class. - /// - /// - /// - /// - /// ZipFile can be used to create or update zip files, or read and extract - /// zip files. ZipInputStream can be used only to read and extract zip - /// files. If you want to use a stream to create zip files, check out the . - /// - /// - /// - /// ZipInputStream cannot read segmented or spanned - /// zip files. - /// - /// - /// - /// ZipInputStream will not read Zip file comments. - /// - /// - /// - /// When reading larger files, ZipInputStream will always underperform - /// ZipFile. This is because the ZipInputStream does a full scan on the - /// zip file, while the ZipFile class reads the central directory of the - /// zip file. - /// - /// - /// - /// - /// - /// - /// - /// The stream to read. It must be readable. This stream will be closed at - /// the time the ZipInputStream is closed. - /// - /// - /// - /// - /// This example shows how to read a zip file, and extract entries, using the - /// ZipInputStream class. - /// - /// - /// private void Unzip() - /// { - /// byte[] buffer= new byte[2048]; - /// int n; - /// using (var raw = File.Open(inputFileName, FileMode.Open, FileAccess.Read)) - /// { - /// using (var input= new ZipInputStream(raw)) - /// { - /// ZipEntry e; - /// while (( e = input.GetNextEntry()) != null) - /// { - /// if (e.IsDirectory) continue; - /// string outputPath = Path.Combine(extractDir, e.FileName); - /// using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite)) - /// { - /// while ((n= input.Read(buffer, 0, buffer.Length)) > 0) - /// { - /// output.Write(buffer,0,n); - /// } - /// } - /// } - /// } - /// } - /// } - /// - /// - /// - /// Private Sub UnZip() - /// Dim inputFileName As String = "MyArchive.zip" - /// Dim extractDir As String = "extract" - /// Dim buffer As Byte() = New Byte(2048) {} - /// Using raw As FileStream = File.Open(inputFileName, FileMode.Open, FileAccess.Read) - /// Using input As ZipInputStream = New ZipInputStream(raw) - /// Dim e As ZipEntry - /// Do While (Not e = input.GetNextEntry Is Nothing) - /// If Not e.IsDirectory Then - /// Using output As FileStream = File.Open(Path.Combine(extractDir, e.FileName), _ - /// FileMode.Create, FileAccess.ReadWrite) - /// Dim n As Integer - /// Do While (n = input.Read(buffer, 0, buffer.Length) > 0) - /// output.Write(buffer, 0, n) - /// Loop - /// End Using - /// End If - /// Loop - /// End Using - /// End Using - /// End Sub - /// - /// - public ZipInputStream(Stream stream) : this (stream, false) { } - - - - /// - /// Create a ZipInputStream, given the name of an existing zip file. - /// - /// - /// - /// - /// - /// This constructor opens a FileStream for the given zipfile, and - /// wraps a ZipInputStream around that. See the documentation for the - /// constructor for full details. - /// - /// - /// - /// While the class is generally easier - /// to use, this class provides an alternative to those - /// applications that want to read from a zipfile directly, - /// using a . - /// - /// - /// - /// - /// - /// The name of the filesystem file to read. - /// - /// - /// - /// - /// This example shows how to read a zip file, and extract entries, using the - /// ZipInputStream class. - /// - /// - /// private void Unzip() - /// { - /// byte[] buffer= new byte[2048]; - /// int n; - /// using (var input= new ZipInputStream(inputFileName)) - /// { - /// ZipEntry e; - /// while (( e = input.GetNextEntry()) != null) - /// { - /// if (e.IsDirectory) continue; - /// string outputPath = Path.Combine(extractDir, e.FileName); - /// using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite)) - /// { - /// while ((n= input.Read(buffer, 0, buffer.Length)) > 0) - /// { - /// output.Write(buffer,0,n); - /// } - /// } - /// } - /// } - /// } - /// - /// - /// - /// Private Sub UnZip() - /// Dim inputFileName As String = "MyArchive.zip" - /// Dim extractDir As String = "extract" - /// Dim buffer As Byte() = New Byte(2048) {} - /// Using input As ZipInputStream = New ZipInputStream(inputFileName) - /// Dim e As ZipEntry - /// Do While (Not e = input.GetNextEntry Is Nothing) - /// If Not e.IsDirectory Then - /// Using output As FileStream = File.Open(Path.Combine(extractDir, e.FileName), _ - /// FileMode.Create, FileAccess.ReadWrite) - /// Dim n As Integer - /// Do While (n = input.Read(buffer, 0, buffer.Length) > 0) - /// output.Write(buffer, 0, n) - /// Loop - /// End Using - /// End If - /// Loop - /// End Using - /// End Sub - /// - /// - public ZipInputStream(String fileName) - { - Stream stream = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read ); - _Init(stream, false, fileName); - } - - - /// - /// Create a ZipInputStream, explicitly specifying whether to - /// keep the underlying stream open. - /// - /// - /// - /// See the documentation for the ZipInputStream(Stream) - /// constructor for a discussion of the class, and an example of how to use the class. - /// - /// - /// - /// The stream to read from. It must be readable. - /// - /// - /// - /// true if the application would like the stream - /// to remain open after the ZipInputStream has been closed. - /// - public ZipInputStream(Stream stream, bool leaveOpen) - { - _Init(stream, leaveOpen, null); - } - - private void _Init(Stream stream, bool leaveOpen, string name) - { - _inputStream = stream; - if (!_inputStream.CanRead) - throw new ZipException("The stream must be readable."); - _container= new ZipContainer(this); - _provisionalAlternateEncoding = System.Text.Encoding.GetEncoding("IBM437"); - _leaveUnderlyingStreamOpen = leaveOpen; - _findRequired= true; - _name = name ?? "(stream)"; - } - - - /// Provides a string representation of the instance. - /// - /// - /// This can be useful for debugging purposes. - /// - /// - /// a string representation of the instance. - public override String ToString() - { - return String.Format ("ZipInputStream::{0}(leaveOpen({1})))", _name, _leaveUnderlyingStreamOpen); - } - - - /// - /// The text encoding to use when reading entries into the zip archive, for - /// those entries whose filenames or comments cannot be encoded with the - /// default (IBM437) encoding. - /// - /// - /// - /// - /// In its - /// zip specification, PKWare describes two options for encoding - /// filenames and comments: using IBM437 or UTF-8. But, some archiving tools - /// or libraries do not follow the specification, and instead encode - /// characters using the system default code page. For example, WinRAR when - /// run on a machine in Shanghai may encode filenames with the Big-5 Chinese - /// (950) code page. This behavior is contrary to the Zip specification, but - /// it occurs anyway. - /// - /// - /// - /// When using DotNetZip to read zip archives that use something other than - /// UTF-8 or IBM437, set this property to specify the code page to use when - /// reading encoded filenames and comments for each ZipEntry in the zip - /// file. - /// - /// - /// - /// This property is "provisional". When the entry in the zip archive is not - /// explicitly marked as using UTF-8, then IBM437 is used to decode filenames - /// and comments. If a loss of data would result from using IBM436 - - /// specifically when encoding and decoding is not reflexive - the codepage - /// specified here is used. It is possible, therefore, to have a given entry - /// with a Comment encoded in IBM437 and a FileName encoded with - /// the specified "provisional" codepage. - /// - /// - /// - /// When a zip file uses an arbitrary, non-UTF8 code page for encoding, there - /// is no standard way for the reader application - whether DotNetZip, WinZip, - /// WinRar, or something else - to know which codepage has been used for the - /// entries. Readers of zip files are not able to inspect the zip file and - /// determine the codepage that was used for the entries contained within it. - /// It is left to the application or user to determine the necessary codepage - /// when reading zip files encoded this way. If you use an incorrect codepage - /// when reading a zipfile, you will get entries with filenames that are - /// incorrect, and the incorrect filenames may even contain characters that - /// are not legal for use within filenames in Windows. Extracting entries with - /// illegal characters in the filenames will lead to exceptions. It's too bad, - /// but this is just the way things are with code pages in zip files. Caveat - /// Emptor. - /// - /// - /// - public System.Text.Encoding ProvisionalAlternateEncoding - { - get - { - return _provisionalAlternateEncoding; - } - set - { - _provisionalAlternateEncoding = value; - } - } - - - /// - /// Size of the work buffer to use for the ZLIB codec during decompression. - /// - /// - /// - /// Setting this affects the performance and memory efficiency of compression - /// and decompression. For larger files, setting this to a larger size may - /// improve performance, but the exact numbers vary depending on available - /// memory, and a bunch of other variables. I don't have good firm - /// recommendations on how to set it. You'll have to test it yourself. Or - /// just leave it alone and accept the default. - /// - public int CodecBufferSize - { - get; - set; - } - - - /// - /// Sets the password to be used on the ZipInputStream instance. - /// - /// - /// - /// - /// - /// When reading a zip archive, this password is used to read and decrypt the - /// entries that are encrypted within the zip file. When entries within a zip - /// file use different passwords, set the appropriate password for the entry - /// before the first call to Read() for each entry. - /// - /// - /// - /// When reading an entry that is not encrypted, the value of this property is - /// ignored. - /// - /// - /// - /// - /// - /// - /// This example uses the ZipInputStream to read and extract entries from a - /// zip file, using a potentially different password for each entry. - /// - /// - /// byte[] buffer= new byte[2048]; - /// int n; - /// using (var raw = File.Open(_inputFileName, FileMode.Open, FileAccess.Read )) - /// { - /// using (var input= new ZipInputStream(raw)) - /// { - /// ZipEntry e; - /// while (( e = input.GetNextEntry()) != null) - /// { - /// input.Password = PasswordForEntry(e.FileName); - /// if (e.IsDirectory) continue; - /// string outputPath = Path.Combine(_extractDir, e.FileName); - /// using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite)) - /// { - /// while ((n= input.Read(buffer,0,buffer.Length)) > 0) - /// { - /// output.Write(buffer,0,n); - /// } - /// } - /// } - /// } - /// } - /// - /// - /// - public String Password - { - set - { - if (_closed) - { - _exceptionPending = true; - throw new System.InvalidOperationException("The stream has been closed."); - } - _Password = value; - } - } - - - private void SetupStream() - { - // Seek to the correct posn in the file, and open a - // stream that can be read. - _crcStream= _currentEntry.InternalOpenReader(_Password); - _LeftToRead = _crcStream.Length; - _needSetup = false; - } - - - - internal Stream ReadStream - { - get - { - return _inputStream; - } - } - - - /// - /// Read the data from the stream into the buffer. - /// - /// - /// - /// - /// The data for the zipentry will be decrypted and uncompressed, as - /// necessary, before being copied into the buffer. - /// - /// - /// - /// You must set the property before calling - /// Read() the first time for an encrypted entry. To determine if an - /// entry is encrypted and requires a password, check the ZipEntry.Encryption property. - /// - /// - /// - /// The buffer to hold the data read from the stream. - /// the offset within the buffer to copy the first byte read. - /// the number of bytes to read. - /// the number of bytes read, after decryption and decompression. - public override int Read(byte[] buffer, int offset, int count) - { - if (_closed) - { - _exceptionPending = true; - throw new System.InvalidOperationException("The stream has been closed."); - } - - if (_needSetup) - SetupStream(); - - if (_LeftToRead == 0) return 0; - - int len = (_LeftToRead > count) ? count : (int)_LeftToRead; - int n = _crcStream.Read(buffer, offset, len); - - _LeftToRead -= n; - - if (_LeftToRead == 0) - { - int CrcResult = _crcStream.Crc; - _currentEntry.VerifyCrcAfterExtract(CrcResult); - _inputStream.Seek(_endOfEntry, SeekOrigin.Begin); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(_inputStream); - } - - return n; - } - - - - /// - /// Read the next entry from the zip file. - /// - /// - /// - /// - /// Call this method just before calling , - /// to position the pointer in the zip file to the next entry that can be - /// read. Subsequent calls to Read(), will decrypt and decompress the - /// data in the zip file, until Read() returns 0. - /// - /// - /// - /// Each time you call GetNextEntry(), the pointer in the wrapped - /// stream is moved to the next entry in the zip file. If you call , and thus re-position the pointer within - /// the file, you will need to call GetNextEntry() again, to insure - /// that the file pointer is positioned at the beginning of a zip entry. - /// - /// - /// - /// This method returns the ZipEntry. Using a stream approach, you will - /// read the raw bytes for an entry in a zip file via calls to Read(). - /// Alternatively, you can extract an entry into a file, or a stream, by - /// calling , or one of its siblings. - /// - /// - /// - /// - /// - /// The ZipEntry read. Returns null (or Nothing in VB) if there are no more - /// entries in the zip file. - /// - /// - public ZipEntry GetNextEntry() - { - if (_findRequired) - { - // find the next signature - long d = SharedUtilities.FindSignature(_inputStream, ZipConstants.ZipEntrySignature); - if (d == -1) return null; - // back up 4 bytes: ReadEntry assumes the file pointer is positioned before the entry signature - _inputStream.Seek(-4, SeekOrigin.Current); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(_inputStream); - } - // workitem 10923 - else if (_firstEntry) - { - // we've already read one entry. - // Seek to the end of it. - _inputStream.Seek(_endOfEntry, SeekOrigin.Begin); - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(_inputStream); - } - - _currentEntry = ZipEntry.ReadEntry(_container, !_firstEntry); - // ReadEntry leaves the file position after all the entry - // data and the optional bit-3 data descriptpr. This is - // where the next entry would normally start. - _endOfEntry = _inputStream.Position; - _firstEntry = true; - _needSetup = true; - _findRequired= false; - return _currentEntry; - } - - - /// - /// Dispose the stream. - /// - /// - /// - /// - /// This method disposes the ZipInputStream. It may also close the - /// underlying stream, depending on which constructor was used. - /// - /// - /// - /// Typically the application will call Dispose() implicitly, via - /// a using statement in C#, or a Using statement in VB. - /// - /// - /// - /// Application code won't call this code directly. This method may - /// be invoked in two distinct scenarios. If disposing == true, the - /// method has been called directly or indirectly by a user's code, - /// for example via the public Dispose() method. In this case, both - /// managed and unmanaged resources can be referenced and disposed. - /// If disposing == false, the method has been called by the runtime - /// from inside the object finalizer and this method should not - /// reference other objects; in that case only unmanaged resources - /// must be referenced or disposed. - /// - /// - /// - /// - /// true if the Dispose method was invoked by user code. - /// - protected override void Dispose(bool disposing) - { - if (_closed) return; - - if (disposing) // not called from finalizer - { - // When ZipInputStream is used within a using clause, and an - // exception is thrown, Close() is invoked. But we don't want to - // try to write anything in that case. Eventually the exception - // will be propagated to the application. - if (_exceptionPending) return; - - if (!_leaveUnderlyingStreamOpen) - { -#if NETCF - _inputStream.Close(); -#else - _inputStream.Dispose(); -#endif - } - } - _closed= true; - } - - - /// - /// Always returns true. - /// - public override bool CanRead { get { return true; }} - - /// - /// Returns the value of CanSeek for the underlying (wrapped) stream. - /// - public override bool CanSeek { get { return _inputStream.CanSeek; } } - - /// - /// Always returns false. - /// - public override bool CanWrite { get { return false; } } - - /// - /// Returns the length of the underlying stream. - /// - public override long Length { get { return _inputStream.Length; }} - - /// - /// Gets or sets the position of the underlying stream. - /// - /// - /// Setting the position is equivalent to calling Seek(value, SeekOrigin.Begin). - /// - public override long Position - { - get { return _inputStream.Position;} - set { Seek(value, SeekOrigin.Begin); } - } - - /// - /// This is a no-op. - /// - public override void Flush() - { - throw new NotSupportedException("Flush"); - } - - - /// - /// This method always throws a NotSupportedException. - /// - /// ignored - /// ignored - /// ignored - public override void Write(byte[] buffer, int offset, int count) - { - throw new NotSupportedException("Write"); - } - - - /// - /// This method seeks in the underlying stream. - /// - /// - /// - /// - /// Call this method if you want to seek around within the zip file for random access. - /// - /// - /// - /// Applications can intermix calls to Seek() with calls to . After a call to Seek(), - /// GetNextEntry() will get the next ZipEntry that falls after - /// the current position in the input stream. You're on your own for finding - /// out just where to seek in the stream, to get to the various entries. - /// - /// - /// - /// - /// the offset point to seek to - /// the reference point from which to seek - /// The new position - public override long Seek(long offset, SeekOrigin origin) - { - _findRequired= true; - var x = _inputStream.Seek(offset, origin); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(_inputStream); - return x; - } - - /// - /// This method always throws a NotSupportedException. - /// - /// ignored - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - - private Stream _inputStream; - private System.Text.Encoding _provisionalAlternateEncoding; - private ZipEntry _currentEntry; - private bool _firstEntry; - private bool _needSetup; - private ZipContainer _container; - private Ionic.Crc.CrcCalculatorStream _crcStream; - private Int64 _LeftToRead; - internal String _Password; - private Int64 _endOfEntry; - private string _name; - - private bool _leaveUnderlyingStreamOpen; - private bool _closed; - private bool _findRequired; - private bool _exceptionPending; - } - - - -} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipOutputStream.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipOutputStream.cs deleted file mode 100644 index 71f7633e..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipOutputStream.cs +++ /dev/null @@ -1,1817 +0,0 @@ -// ZipOutputStream.cs -// -// ------------------------------------------------------------------ -// -// Copyright (c) 2009 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-28 06:34:30> -// -// ------------------------------------------------------------------ -// -// This module defines the ZipOutputStream class, which is a stream metaphor for -// generating zip files. This class does not depend on Ionic.Zip.ZipFile, but rather -// stands alongside it as an alternative "container" for ZipEntry. It replicates a -// subset of the properties, including these: -// -// - Comment -// - Encryption -// - Password -// - CodecBufferSize -// - CompressionLevel -// - CompressionMethod -// - EnableZip64 (UseZip64WhenSaving) -// - IgnoreCase (!CaseSensitiveRetrieval) -// -// It adds these novel methods: -// -// - PutNextEntry -// -// -// ------------------------------------------------------------------ -// - -using System; -using System.Threading; -using System.Collections.Generic; -using System.IO; -using Ionic.Zip; - -namespace Ionic.Zip -{ - /// - /// Provides a stream metaphor for generating zip files. - /// - /// - /// - /// - /// This class writes zip files, as defined in the specification - /// for zip files described by PKWare. The compression for this - /// implementation is provided by a managed-code version of Zlib, included with - /// DotNetZip in the classes in the Ionic.Zlib namespace. - /// - /// - /// - /// This class provides an alternative programming model to the one enabled by the - /// class. Use this when creating zip files, as an - /// alternative to the class, when you would like to use a - /// Stream type to write the zip file. - /// - /// - /// - /// Both the ZipOutputStream class and the ZipFile class can be used - /// to create zip files. Both of them support many of the common zip features, - /// including Unicode, different compression levels, and ZIP64. They provide - /// very similar performance when creating zip files. - /// - /// - /// - /// The ZipFile class is generally easier to use than - /// ZipOutputStream and should be considered a higher-level interface. For - /// example, when creating a zip file via calls to the PutNextEntry() and - /// Write() methods on the ZipOutputStream class, the caller is - /// responsible for opening the file, reading the bytes from the file, writing - /// those bytes into the ZipOutputStream, setting the attributes on the - /// ZipEntry, and setting the created, last modified, and last accessed - /// timestamps on the zip entry. All of these things are done automatically by a - /// call to ZipFile.AddFile(). - /// For this reason, the ZipOutputStream is generally recommended for use - /// only when your application emits arbitrary data, not necessarily data from a - /// filesystem file, directly into a zip file, and does so using a Stream - /// metaphor. - /// - /// - /// - /// Aside from the differences in programming model, there are other - /// differences in capability between the two classes. - /// - /// - /// - /// - /// ZipFile can be used to read and extract zip files, in addition to - /// creating zip files. ZipOutputStream cannot read zip files. If you want - /// to use a stream to read zip files, check out the class. - /// - /// - /// - /// ZipOutputStream does not support the creation of segmented or spanned - /// zip files. - /// - /// - /// - /// ZipOutputStream cannot produce a self-extracting archive. - /// - /// - /// - /// - /// Be aware that the ZipOutputStream class implements the interface. In order for - /// ZipOutputStream to produce a valid zip file, you use use it within - /// a using clause (Using in VB), or call the Dispose() method - /// explicitly. See the examples for how to employ a using clause. - /// - /// - /// - /// Also, a note regarding compression performance: On the desktop .NET - /// Framework, DotNetZip can use a multi-threaded compression implementation - /// that provides significant speed increases on large files, over 300k or so, - /// at the cost of increased memory use at runtime. (The output of the - /// compression is almost exactly the same size). But, the multi-threaded - /// approach incurs a performance hit on smaller files. There's no way for the - /// ZipOutputStream to know whether parallel compression will be beneficial, - /// because the ZipOutputStream does not know how much data you will write - /// through the stream. You may wish to set the property to zero, if you are compressing - /// large files through ZipOutputStream. This will cause parallel - /// compression to be used, always. - /// - /// - public class ZipOutputStream : Stream - { - /// - /// Create a ZipOutputStream, wrapping an existing stream. - /// - /// - /// - /// - /// The class is generally easier to use when creating - /// zip files. The ZipOutputStream offers a different metaphor for creating a - /// zip file, based on the class. - /// - /// - /// - /// - /// - /// The stream to wrap. It must be writable. This stream will be closed at - /// the time the ZipOutputStream is closed. - /// - /// - /// - /// - /// This example shows how to create a zip file, using the - /// ZipOutputStream class. - /// - /// - /// private void Zipup() - /// { - /// if (filesToZip.Count == 0) - /// { - /// System.Console.WriteLine("Nothing to do."); - /// return; - /// } - /// - /// using (var raw = File.Open(_outputFileName, FileMode.Create, FileAccess.ReadWrite )) - /// { - /// using (var output= new ZipOutputStream(raw)) - /// { - /// output.Password = "VerySecret!"; - /// output.Encryption = EncryptionAlgorithm.WinZipAes256; - /// - /// foreach (string inputFileName in filesToZip) - /// { - /// System.Console.WriteLine("file: {0}", inputFileName); - /// - /// output.PutNextEntry(inputFileName); - /// using (var input = File.Open(inputFileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Write )) - /// { - /// byte[] buffer= new byte[2048]; - /// int n; - /// while ((n= input.Read(buffer,0,buffer.Length)) > 0) - /// { - /// output.Write(buffer,0,n); - /// } - /// } - /// } - /// } - /// } - /// } - /// - /// - /// - /// Private Sub Zipup() - /// Dim outputFileName As String = "XmlData.zip" - /// Dim filesToZip As String() = Directory.GetFiles(".", "*.xml") - /// If (filesToZip.Length = 0) Then - /// Console.WriteLine("Nothing to do.") - /// Else - /// Using raw As FileStream = File.Open(outputFileName, FileMode.Create, FileAccess.ReadWrite) - /// Using output As ZipOutputStream = New ZipOutputStream(raw) - /// output.Password = "VerySecret!" - /// output.Encryption = EncryptionAlgorithm.WinZipAes256 - /// Dim inputFileName As String - /// For Each inputFileName In filesToZip - /// Console.WriteLine("file: {0}", inputFileName) - /// output.PutNextEntry(inputFileName) - /// Using input As FileStream = File.Open(inputFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) - /// Dim n As Integer - /// Dim buffer As Byte() = New Byte(2048) {} - /// Do While (n = input.Read(buffer, 0, buffer.Length) > 0) - /// output.Write(buffer, 0, n) - /// Loop - /// End Using - /// Next - /// End Using - /// End Using - /// End If - /// End Sub - /// - /// - public ZipOutputStream(Stream stream) : this(stream, false) { } - - - /// - /// Create a ZipOutputStream that writes to a filesystem file. - /// - /// - /// - /// The class is generally easier to use when creating - /// zip files. The ZipOutputStream offers a different metaphor for creating a - /// zip file, based on the class. - /// - /// - /// - /// The name of the zip file to create. - /// - /// - /// - /// - /// This example shows how to create a zip file, using the - /// ZipOutputStream class. - /// - /// - /// private void Zipup() - /// { - /// if (filesToZip.Count == 0) - /// { - /// System.Console.WriteLine("Nothing to do."); - /// return; - /// } - /// - /// using (var output= new ZipOutputStream(outputFileName)) - /// { - /// output.Password = "VerySecret!"; - /// output.Encryption = EncryptionAlgorithm.WinZipAes256; - /// - /// foreach (string inputFileName in filesToZip) - /// { - /// System.Console.WriteLine("file: {0}", inputFileName); - /// - /// output.PutNextEntry(inputFileName); - /// using (var input = File.Open(inputFileName, FileMode.Open, FileAccess.Read, - /// FileShare.Read | FileShare.Write )) - /// { - /// byte[] buffer= new byte[2048]; - /// int n; - /// while ((n= input.Read(buffer,0,buffer.Length)) > 0) - /// { - /// output.Write(buffer,0,n); - /// } - /// } - /// } - /// } - /// } - /// - /// - /// - /// Private Sub Zipup() - /// Dim outputFileName As String = "XmlData.zip" - /// Dim filesToZip As String() = Directory.GetFiles(".", "*.xml") - /// If (filesToZip.Length = 0) Then - /// Console.WriteLine("Nothing to do.") - /// Else - /// Using output As ZipOutputStream = New ZipOutputStream(outputFileName) - /// output.Password = "VerySecret!" - /// output.Encryption = EncryptionAlgorithm.WinZipAes256 - /// Dim inputFileName As String - /// For Each inputFileName In filesToZip - /// Console.WriteLine("file: {0}", inputFileName) - /// output.PutNextEntry(inputFileName) - /// Using input As FileStream = File.Open(inputFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) - /// Dim n As Integer - /// Dim buffer As Byte() = New Byte(2048) {} - /// Do While (n = input.Read(buffer, 0, buffer.Length) > 0) - /// output.Write(buffer, 0, n) - /// Loop - /// End Using - /// Next - /// End Using - /// End If - /// End Sub - /// - /// - public ZipOutputStream(String fileName) - { - Stream stream = File.Open(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.None); - _Init(stream, false, fileName); - } - - - /// - /// Create a ZipOutputStream. - /// - /// - /// - /// See the documentation for the ZipOutputStream(Stream) - /// constructor for an example. - /// - /// - /// - /// The stream to wrap. It must be writable. - /// - /// - /// - /// true if the application would like the stream - /// to remain open after the ZipOutputStream has been closed. - /// - public ZipOutputStream(Stream stream, bool leaveOpen) - { - _Init(stream, leaveOpen, null); - } - - private void _Init(Stream stream, bool leaveOpen, string name) - { - // workitem 9307 - _outputStream = stream.CanRead ? stream : new CountingStream(stream); - CompressionLevel = Ionic.Zlib.CompressionLevel.Default; - CompressionMethod = Ionic.Zip.CompressionMethod.Deflate; - _encryption = EncryptionAlgorithm.None; - _entriesWritten = new Dictionary(StringComparer.Ordinal); - _zip64 = Zip64Option.Never; - _leaveUnderlyingStreamOpen = leaveOpen; - Strategy = Ionic.Zlib.CompressionStrategy.Default; - _name = name ?? "(stream)"; -#if !NETCF - ParallelDeflateThreshold = -1L; -#endif - } - - - /// Provides a string representation of the instance. - /// - /// - /// This can be useful for debugging purposes. - /// - /// - /// a string representation of the instance. - public override String ToString() - { - return String.Format ("ZipOutputStream::{0}(leaveOpen({1})))", _name, _leaveUnderlyingStreamOpen); - } - - - /// - /// Sets the password to be used on the ZipOutputStream instance. - /// - /// - /// - /// - /// - /// When writing a zip archive, this password is applied to the entries, not - /// to the zip archive itself. It applies to any ZipEntry subsequently - /// written to the ZipOutputStream. - /// - /// - /// - /// Using a password does not encrypt or protect the "directory" of the - /// archive - the list of entries contained in the archive. If you set the - /// Password property, the password actually applies to individual - /// entries that are added to the archive, subsequent to the setting of this - /// property. The list of filenames in the archive that is eventually created - /// will appear in clear text, but the contents of the individual files are - /// encrypted. This is how Zip encryption works. - /// - /// - /// - /// If you set this property, and then add a set of entries to the archive via - /// calls to PutNextEntry, then each entry is encrypted with that - /// password. You may also want to change the password between adding - /// different entries. If you set the password, add an entry, then set the - /// password to null (Nothing in VB), and add another entry, the - /// first entry is encrypted and the second is not. - /// - /// - /// - /// When setting the Password, you may also want to explicitly set the property, to specify how to encrypt the entries added - /// to the ZipFile. If you set the Password to a non-null value and do not - /// set , then PKZip 2.0 ("Weak") encryption is used. - /// This encryption is relatively weak but is very interoperable. If - /// you set the password to a null value (Nothing in VB), - /// Encryption is reset to None. - /// - /// - /// - /// Special case: if you wrap a ZipOutputStream around a non-seekable stream, - /// and use encryption, and emit an entry of zero bytes, the Close() or - /// PutNextEntry() following the entry will throw an exception. - /// - /// - /// - public String Password - { - set - { - if (_disposed) - { - _exceptionPending = true; - throw new System.InvalidOperationException("The stream has been closed."); - } - - _password = value; - if (_password == null) - { - _encryption = EncryptionAlgorithm.None; - } - else if (_encryption == EncryptionAlgorithm.None) - { - _encryption = EncryptionAlgorithm.PkzipWeak; - } - } - } - - - /// - /// The Encryption to use for entries added to the ZipOutputStream. - /// - /// - /// - /// - /// The specified Encryption is applied to the entries subsequently - /// written to the ZipOutputStream instance. - /// - /// - /// - /// If you set this to something other than - /// EncryptionAlgorithm.None, you will also need to set the - /// to a non-null, non-empty value in - /// order to actually get encryption on the entry. - /// - /// - /// - /// - /// ZipOutputStream.Password - /// ZipEntry.Encryption - public EncryptionAlgorithm Encryption - { - get - { - return _encryption; - } - set - { - if (_disposed) - { - _exceptionPending = true; - throw new System.InvalidOperationException("The stream has been closed."); - } - if (value == EncryptionAlgorithm.Unsupported) - { - _exceptionPending = true; - throw new InvalidOperationException("You may not set Encryption to that value."); - } - _encryption = value; - } - } - - - /// - /// Size of the work buffer to use for the ZLIB codec during compression. - /// - /// - /// - /// Setting this may affect performance. For larger files, setting this to a - /// larger size may improve performance, but I'm not sure. Sorry, I don't - /// currently have good recommendations on how to set it. You can test it if - /// you like. - /// - public int CodecBufferSize - { - get; - set; - } - - - /// - /// The compression strategy to use for all entries. - /// - /// - /// - /// Set the Strategy used by the ZLIB-compatible compressor, when compressing - /// data for the entries in the zip archive. Different compression strategies - /// work better on different sorts of data. The strategy parameter can affect - /// the compression ratio and the speed of compression but not the correctness - /// of the compresssion. For more information see . - /// - public Ionic.Zlib.CompressionStrategy Strategy - { - get; - set; - } - - - /// - /// The type of timestamp attached to the ZipEntry. - /// - /// - /// - /// Set this in order to specify the kind of timestamp that should be emitted - /// into the zip file for each entry. - /// - public ZipEntryTimestamp Timestamp - { - get - { - return _timestamp; - } - set - { - if (_disposed) - { - _exceptionPending = true; - throw new System.InvalidOperationException("The stream has been closed."); - } - _timestamp = value; - } - } - - - /// - /// Sets the compression level to be used for entries subsequently added to - /// the zip archive. - /// - /// - /// - /// - /// Varying the compression level used on entries can affect the - /// size-vs-speed tradeoff when compression and decompressing data streams - /// or files. - /// - /// - /// - /// As with some other properties on the ZipOutputStream class, like , and , - /// setting this property on a ZipOutputStream - /// instance will cause the specified CompressionLevel to be used on all - /// items that are subsequently added to the - /// ZipOutputStream instance. - /// - /// - /// - /// If you do not set this property, the default compression level is used, - /// which normally gives a good balance of compression efficiency and - /// compression speed. In some tests, using BestCompression can - /// double the time it takes to compress, while delivering just a small - /// increase in compression efficiency. This behavior will vary with the - /// type of data you compress. If you are in doubt, just leave this setting - /// alone, and accept the default. - /// - /// - public Ionic.Zlib.CompressionLevel CompressionLevel - { - get; - set; - } - - /// - /// The compression method used on each entry added to the ZipOutputStream. - /// - public Ionic.Zip.CompressionMethod CompressionMethod - { - get; - set; - } - - - /// - /// A comment attached to the zip archive. - /// - /// - /// - /// - /// - /// The application sets this property to specify a comment to be embedded - /// into the generated zip archive. - /// - /// - /// - /// According to PKWARE's - /// zip specification, the comment is not encrypted, even if there is a - /// password set on the zip file. - /// - /// - /// - /// The specification does not describe how to indicate the encoding used - /// on a comment string. Many "compliant" zip tools and libraries use - /// IBM437 as the code page for comments; DotNetZip, too, follows that - /// practice. On the other hand, there are situations where you want a - /// Comment to be encoded with something else, for example using code page - /// 950 "Big-5 Chinese". To fill that need, DotNetZip will encode the - /// comment following the same procedure it follows for encoding - /// filenames: (a) if is - /// Never, it uses the default encoding (IBM437). (b) if is Always, it always uses the - /// alternate encoding (). (c) if is AsNecessary, it uses the - /// alternate encoding only if the default encoding is not sufficient for - /// encoding the comment - in other words if decoding the result does not - /// produce the original string. This decision is taken at the time of - /// the call to ZipFile.Save(). - /// - /// - /// - public string Comment - { - get { return _comment; } - set - { - if (_disposed) - { - _exceptionPending = true; - throw new System.InvalidOperationException("The stream has been closed."); - } - _comment = value; - } - } - - - - /// - /// Specify whether to use ZIP64 extensions when saving a zip archive. - /// - /// - /// - /// - /// The default value for the property is . is - /// safest, in the sense that you will not get an Exception if a - /// pre-ZIP64 limit is exceeded. - /// - /// - /// - /// You must set this property before calling Write(). - /// - /// - /// - public Zip64Option EnableZip64 - { - get - { - return _zip64; - } - set - { - if (_disposed) - { - _exceptionPending = true; - throw new System.InvalidOperationException("The stream has been closed."); - } - _zip64 = value; - } - } - - - /// - /// Indicates whether ZIP64 extensions were used when saving the zip archive. - /// - /// - /// - /// The value is defined only after the ZipOutputStream has been closed. - /// - public bool OutputUsedZip64 - { - get - { - return _anyEntriesUsedZip64 || _directoryNeededZip64; - } - } - - - /// - /// Whether the ZipOutputStream should use case-insensitive comparisons when - /// checking for uniqueness of zip entries. - /// - /// - /// - /// - /// Though the zip specification doesn't prohibit zipfiles with duplicate - /// entries, Sane zip files have no duplicates, and the DotNetZip library - /// cannot create zip files with duplicate entries. If an application attempts - /// to call with a name that duplicates one - /// already used within the archive, the library will throw an Exception. - /// - /// - /// This property allows the application to specify whether the - /// ZipOutputStream instance considers ordinal case when checking for - /// uniqueness of zip entries. - /// - /// - public bool IgnoreCase - { - get - { - return !_DontIgnoreCase; - } - - set - { - _DontIgnoreCase = !value; - } - - } - - - /// - /// Indicates whether to encode entry filenames and entry comments using - /// Unicode (UTF-8). - /// - /// - /// - /// - /// The - /// PKWare zip specification provides for encoding file names and file - /// comments in either the IBM437 code page, or in UTF-8. This flag selects - /// the encoding according to that specification. By default, this flag is - /// false, and filenames and comments are encoded into the zip file in the - /// IBM437 codepage. Setting this flag to true will specify that filenames - /// and comments that cannot be encoded with IBM437 will be encoded with - /// UTF-8. - /// - /// - /// - /// Zip files created with strict adherence to the PKWare specification with - /// respect to UTF-8 encoding can contain entries with filenames containing - /// any combination of Unicode characters, including the full range of - /// characters from Chinese, Latin, Hebrew, Greek, Cyrillic, and many other - /// alphabets. However, because at this time, the UTF-8 portion of the PKWare - /// specification is not broadly supported by other zip libraries and - /// utilities, such zip files may not be readable by your favorite zip tool or - /// archiver. In other words, interoperability will decrease if you set this - /// flag to true. - /// - /// - /// - /// In particular, Zip files created with strict adherence to the PKWare - /// specification with respect to UTF-8 encoding will not work well with - /// Explorer in Windows XP or Windows Vista, because Windows compressed - /// folders, as far as I know, do not support UTF-8 in zip files. Vista can - /// read the zip files, but shows the filenames incorrectly. Unpacking from - /// Windows Vista Explorer will result in filenames that have rubbish - /// characters in place of the high-order UTF-8 bytes. - /// - /// - /// - /// Also, zip files that use UTF-8 encoding will not work well with Java - /// applications that use the java.util.zip classes, as of v5.0 of the Java - /// runtime. The Java runtime does not correctly implement the PKWare - /// specification in this regard. - /// - /// - /// - /// As a result, we have the unfortunate situation that "correct" behavior by - /// the DotNetZip library with regard to Unicode encoding of filenames during - /// zip creation will result in zip files that are readable by strictly - /// compliant and current tools (for example the most recent release of the - /// commercial WinZip tool); but these zip files will not be readable by - /// various other tools or libraries, including Windows Explorer. - /// - /// - /// - /// The DotNetZip library can read and write zip files with UTF8-encoded - /// entries, according to the PKware spec. If you use DotNetZip for both - /// creating and reading the zip file, and you use UTF-8, there will be no - /// loss of information in the filenames. For example, using a self-extractor - /// created by this library will allow you to unpack files correctly with no - /// loss of information in the filenames. - /// - /// - /// - /// If you do not set this flag, it will remain false. If this flag is false, - /// the ZipOutputStream will encode all filenames and comments using - /// the IBM437 codepage. This can cause "loss of information" on some - /// filenames, but the resulting zipfile will be more interoperable with other - /// utilities. As an example of the loss of information, diacritics can be - /// lost. The o-tilde character will be down-coded to plain o. The c with a - /// cedilla (Unicode 0xE7) used in Portugese will be downcoded to a c. - /// Likewise, the O-stroke character (Unicode 248), used in Danish and - /// Norwegian, will be down-coded to plain o. Chinese characters cannot be - /// represented in codepage IBM437; when using the default encoding, Chinese - /// characters in filenames will be represented as ?. These are all examples - /// of "information loss". - /// - /// - /// - /// The loss of information associated to the use of the IBM437 encoding is - /// inconvenient, and can also lead to runtime errors. For example, using - /// IBM437, any sequence of 4 Chinese characters will be encoded as ????. If - /// your application creates a ZipOutputStream, does not set the - /// encoding, then adds two files, each with names of four Chinese characters - /// each, this will result in a duplicate filename exception. In the case - /// where you add a single file with a name containing four Chinese - /// characters, the zipfile will save properly, but extracting that file - /// later, with any zip tool, will result in an error, because the question - /// mark is not legal for use within filenames on Windows. These are just a - /// few examples of the problems associated to loss of information. - /// - /// - /// - /// This flag is independent of the encoding of the content within the entries - /// in the zip file. Think of the zip file as a container - it supports an - /// encoding. Within the container are other "containers" - the file entries - /// themselves. The encoding within those entries is independent of the - /// encoding of the zip archive container for those entries. - /// - /// - /// - /// Rather than specify the encoding in a binary fashion using this flag, an - /// application can specify an arbitrary encoding via the property. Setting the encoding - /// explicitly when creating zip archives will result in non-compliant zip - /// files that, curiously, are fairly interoperable. The challenge is, the - /// PKWare specification does not provide for a way to specify that an entry - /// in a zip archive uses a code page that is neither IBM437 nor UTF-8. - /// Therefore if you set the encoding explicitly when creating a zip archive, - /// you must take care upon reading the zip archive to use the same code page. - /// If you get it wrong, the behavior is undefined and may result in incorrect - /// filenames, exceptions, stomach upset, hair loss, and acne. - /// - /// - /// - [Obsolete("Beginning with v1.9.1.6 of DotNetZip, this property is obsolete. It will be removed in a future version of the library. Use AlternateEncoding and AlternateEncodingUsage instead.")] - public bool UseUnicodeAsNecessary - { - get - { - return (_alternateEncoding == System.Text.Encoding.UTF8) && - (AlternateEncodingUsage == ZipOption.AsNecessary); - } - set - { - if (value) - { - _alternateEncoding = System.Text.Encoding.UTF8; - _alternateEncodingUsage = ZipOption.AsNecessary; - - } - else - { - _alternateEncoding = Ionic.Zip.ZipOutputStream.DefaultEncoding; - _alternateEncodingUsage = ZipOption.Never; - } - } - } - - - /// - /// The text encoding to use when emitting entries into the zip archive, for - /// those entries whose filenames or comments cannot be encoded with the - /// default (IBM437) encoding. - /// - /// - /// - /// - /// In its - /// zip specification, PKWare describes two options for encoding - /// filenames and comments: using IBM437 or UTF-8. But, some archiving tools - /// or libraries do not follow the specification, and instead encode - /// characters using the system default code page. For example, WinRAR when - /// run on a machine in Shanghai may encode filenames with the Big-5 Chinese - /// (950) code page. This behavior is contrary to the Zip specification, but - /// it occurs anyway. - /// - /// - /// - /// When using DotNetZip to write zip archives that will be read by one of - /// these other archivers, set this property to specify the code page to use - /// when encoding the and for each ZipEntry in the zip file, for - /// values that cannot be encoded with the default codepage for zip files, - /// IBM437. This is why this property is "provisional". In all cases, IBM437 - /// is used where possible, in other words, where no loss of data would - /// result. It is possible, therefore, to have a given entry with a - /// Comment encoded in IBM437 and a FileName encoded with the - /// specified "provisional" codepage. - /// - /// - /// - /// Be aware that a zip file created after you've explicitly set the - /// ProvisionalAlternateEncoding property to a value other than - /// IBM437 may not be compliant to the PKWare specification, and may not be - /// readable by compliant archivers. On the other hand, many (most?) - /// archivers are non-compliant and can read zip files created in arbitrary - /// code pages. The trick is to use or specify the proper codepage when - /// reading the zip. - /// - /// - /// - /// When creating a zip archive using this library, it is possible to change - /// the value of ProvisionalAlternateEncoding between each entry you - /// add, and between adding entries and the call to Close(). Don't do - /// this. It will likely result in a zipfile that is not readable. For best - /// interoperability, either leave ProvisionalAlternateEncoding - /// alone, or specify it only once, before adding any entries to the - /// ZipOutputStream instance. There is one exception to this - /// recommendation, described later. - /// - /// - /// - /// When using an arbitrary, non-UTF8 code page for encoding, there is no - /// standard way for the creator application - whether DotNetZip, WinZip, - /// WinRar, or something else - to formally specify in the zip file which - /// codepage has been used for the entries. As a result, readers of zip files - /// are not able to inspect the zip file and determine the codepage that was - /// used for the entries contained within it. It is left to the application - /// or user to determine the necessary codepage when reading zip files encoded - /// this way. If you use an incorrect codepage when reading a zipfile, you - /// will get entries with filenames that are incorrect, and the incorrect - /// filenames may even contain characters that are not legal for use within - /// filenames in Windows. Extracting entries with illegal characters in the - /// filenames will lead to exceptions. It's too bad, but this is just the way - /// things are with code pages in zip files. Caveat Emptor. - /// - /// - /// - /// One possible approach for specifying the code page for a given zip file is - /// to describe the code page in a human-readable form in the Zip comment. For - /// example, the comment may read "Entries in this archive are encoded in the - /// Big5 code page". For maximum interoperability, the zip comment in this - /// case should be encoded in the default, IBM437 code page. In this case, - /// the zip comment is encoded using a different page than the filenames. To - /// do this, Specify ProvisionalAlternateEncoding to your desired - /// region-specific code page, once before adding any entries, and then set - /// the property and reset - /// ProvisionalAlternateEncoding to IBM437 before calling Close(). - /// - /// - [Obsolete("use AlternateEncoding and AlternateEncodingUsage instead.")] - public System.Text.Encoding ProvisionalAlternateEncoding - { - get - { - if (_alternateEncodingUsage == ZipOption.AsNecessary) - return _alternateEncoding; - return null; - } - set - { - _alternateEncoding = value; - _alternateEncodingUsage = ZipOption.AsNecessary; - } - } - - /// - /// A Text Encoding to use when encoding the filenames and comments for - /// all the ZipEntry items, during a ZipFile.Save() operation. - /// - /// - /// - /// Whether the encoding specified here is used during the save depends - /// on . - /// - /// - public System.Text.Encoding AlternateEncoding - { - get - { - return _alternateEncoding; - } - set - { - _alternateEncoding = value; - } - } - - /// - /// A flag that tells if and when this instance should apply - /// AlternateEncoding to encode the filenames and comments associated to - /// of ZipEntry objects contained within this instance. - /// - public ZipOption AlternateEncodingUsage - { - get - { - return _alternateEncodingUsage; - } - set - { - _alternateEncodingUsage = value; - } - } - - /// - /// The default text encoding used in zip archives. It is numeric 437, also - /// known as IBM437. - /// - /// - public static System.Text.Encoding DefaultEncoding - { - get - { - return System.Text.Encoding.GetEncoding("IBM437"); - } - } - - -#if !NETCF - /// - /// The size threshold for an entry, above which a parallel deflate is used. - /// - /// - /// - /// - /// - /// DotNetZip will use multiple threads to compress any ZipEntry, when - /// the CompressionMethod is Deflate, and if the entry is - /// larger than the given size. Zero means "always use parallel - /// deflate", while -1 means "never use parallel deflate". - /// - /// - /// - /// If the entry size cannot be known before compression, as with any entry - /// added via a ZipOutputStream, then Parallel deflate will never be - /// performed, unless the value of this property is zero. - /// - /// - /// - /// A parallel deflate operations will speed up the compression of - /// large files, on computers with multiple CPUs or multiple CPU - /// cores. For files above 1mb, on a dual core or dual-cpu (2p) - /// machine, the time required to compress the file can be 70% of the - /// single-threaded deflate. For very large files on 4p machines the - /// compression can be done in 30% of the normal time. The downside - /// is that parallel deflate consumes extra memory during the deflate, - /// and the deflation is slightly less effective. - /// - /// - /// - /// Parallel deflate tends to not be as effective as single-threaded deflate - /// because the original data stream is split into multiple independent - /// buffers, each of which is compressed in parallel. But because they are - /// treated independently, there is no opportunity to share compression - /// dictionaries, and additional framing bytes must be added to the output - /// stream. For that reason, a deflated stream may be slightly larger when - /// compressed using parallel deflate, as compared to a traditional - /// single-threaded deflate. For files of about 512k, the increase over the - /// normal deflate is as much as 5% of the total compressed size. For larger - /// files, the difference can be as small as 0.1%. - /// - /// - /// - /// Multi-threaded compression does not give as much an advantage when using - /// Encryption. This is primarily because encryption tends to slow down - /// the entire pipeline. Also, multi-threaded compression gives less of an - /// advantage when using lower compression levels, for example . You may have to perform - /// some tests to determine the best approach for your situation. - /// - /// - /// - /// The default value for this property is -1, which means parallel - /// compression will not be performed unless you set it to zero. - /// - /// - /// - public long ParallelDeflateThreshold - { - set - { - if ((value != 0) && (value != -1) && (value < 64 * 1024)) - throw new ArgumentOutOfRangeException("value must be greater than 64k, or 0, or -1"); - _ParallelDeflateThreshold = value; - } - get - { - return _ParallelDeflateThreshold; - } - } - - - /// - /// The maximum number of buffer pairs to use when performing - /// parallel compression. - /// - /// - /// - /// - /// This property sets an upper limit on the number of memory - /// buffer pairs to create when performing parallel - /// compression. The implementation of the parallel - /// compression stream allocates multiple buffers to - /// facilitate parallel compression. As each buffer fills up, - /// the stream uses - /// ThreadPool.QueueUserWorkItem() to compress those - /// buffers in a background threadpool thread. After a buffer - /// is compressed, it is re-ordered and written to the output - /// stream. - /// - /// - /// - /// A higher number of buffer pairs enables a higher degree of - /// parallelism, which tends to increase the speed of compression on - /// multi-cpu computers. On the other hand, a higher number of buffer - /// pairs also implies a larger memory consumption, more active worker - /// threads, and a higher cpu utilization for any compression. This - /// property enables the application to limit its memory consumption and - /// CPU utilization behavior depending on requirements. - /// - /// - /// - /// For each compression "task" that occurs in parallel, there are 2 - /// buffers allocated: one for input and one for output. This property - /// sets a limit for the number of pairs. The total amount of storage - /// space allocated for buffering will then be (N*S*2), where N is the - /// number of buffer pairs, S is the size of each buffer (). By default, DotNetZip allocates 4 buffer - /// pairs per CPU core, so if your machine has 4 cores, and you retain - /// the default buffer size of 128k, then the - /// ParallelDeflateOutputStream will use 4 * 4 * 2 * 128kb of buffer - /// memory in total, or 4mb, in blocks of 128kb. If you then set this - /// property to 8, then the number will be 8 * 2 * 128kb of buffer - /// memory, or 2mb. - /// - /// - /// - /// CPU utilization will also go up with additional buffers, because a - /// larger number of buffer pairs allows a larger number of background - /// threads to compress in parallel. If you find that parallel - /// compression is consuming too much memory or CPU, you can adjust this - /// value downward. - /// - /// - /// - /// The default value is 16. Different values may deliver better or - /// worse results, depending on your priorities and the dynamic - /// performance characteristics of your storage and compute resources. - /// - /// - /// - /// This property is not the number of buffer pairs to use; it is an - /// upper limit. An illustration: Suppose you have an application that - /// uses the default value of this property (which is 16), and it runs - /// on a machine with 2 CPU cores. In that case, DotNetZip will allocate - /// 4 buffer pairs per CPU core, for a total of 8 pairs. The upper - /// limit specified by this property has no effect. - /// - /// - /// - /// The application can set this value at any time, but it is - /// effective only if set before calling - /// ZipOutputStream.Write() for the first time. - /// - /// - /// - /// - /// - public int ParallelDeflateMaxBufferPairs - { - get - { - return _maxBufferPairs; - } - set - { - if (value < 4) - throw new ArgumentOutOfRangeException("ParallelDeflateMaxBufferPairs", - "Value must be 4 or greater."); - _maxBufferPairs = value; - } - } -#endif - - - private void InsureUniqueEntry(ZipEntry ze1) - { - if (_entriesWritten.ContainsKey(ze1.FileName)) - { - _exceptionPending = true; - throw new ArgumentException(String.Format("The entry '{0}' already exists in the zip archive.", ze1.FileName)); - } - } - - - internal Stream OutputStream - { - get - { - return _outputStream; - } - } - - internal String Name - { - get - { - return _name; - } - } - - /// - /// Returns true if an entry by the given name has already been written - /// to the ZipOutputStream. - /// - /// - /// - /// The name of the entry to scan for. - /// - /// - /// - /// true if an entry by the given name has already been written. - /// - public bool ContainsEntry(string name) - { - return _entriesWritten.ContainsKey(SharedUtilities.NormalizePathForUseInZipFile(name)); - } - - - /// - /// Write the data from the buffer to the stream. - /// - /// - /// - /// As the application writes data into this stream, the data may be - /// compressed and encrypted before being written out to the underlying - /// stream, depending on the settings of the - /// and the properties. - /// - /// - /// The buffer holding data to write to the stream. - /// the offset within that data array to find the first byte to write. - /// the number of bytes to write. - public override void Write(byte[] buffer, int offset, int count) - { - if (_disposed) - { - _exceptionPending = true; - throw new System.InvalidOperationException("The stream has been closed."); - } - - if (buffer==null) - { - _exceptionPending = true; - throw new System.ArgumentNullException("buffer"); - } - - if (_currentEntry == null) - { - _exceptionPending = true; - throw new System.InvalidOperationException("You must call PutNextEntry() before calling Write()."); - } - - if (_currentEntry.IsDirectory) - { - _exceptionPending = true; - throw new System.InvalidOperationException("You cannot Write() data for an entry that is a directory."); - } - - if (_needToWriteEntryHeader) - _InitiateCurrentEntry(false); - - if (count != 0) - _entryOutputStream.Write(buffer, offset, count); - } - - - - /// - /// Specify the name of the next entry that will be written to the zip file. - /// - /// - /// - /// - /// Call this method just before calling , to - /// specify the name of the entry that the next set of bytes written to - /// the ZipOutputStream belongs to. All subsequent calls to Write, - /// until the next call to PutNextEntry, - /// will be inserted into the named entry in the zip file. - /// - /// - /// - /// If the used in PutNextEntry() ends in - /// a slash, then the entry added is marked as a directory. Because directory - /// entries do not contain data, a call to Write(), before an - /// intervening additional call to PutNextEntry(), will throw an - /// exception. - /// - /// - /// - /// If you don't call Write() between two calls to - /// PutNextEntry(), the first entry is inserted into the zip file as a - /// file of zero size. This may be what you want. - /// - /// - /// - /// Because PutNextEntry() closes out the prior entry, if any, this - /// method may throw if there is a problem with the prior entry. - /// - /// - /// - /// This method returns the ZipEntry. You can modify public properties - /// on the ZipEntry, such as , , and so on, until the first call to - /// ZipOutputStream.Write(), or until the next call to - /// PutNextEntry(). If you modify the ZipEntry after - /// having called Write(), you may get a runtime exception, or you may - /// silently get an invalid zip archive. - /// - /// - /// - /// - /// - /// - /// This example shows how to create a zip file, using the - /// ZipOutputStream class. - /// - /// - /// private void Zipup() - /// { - /// using (FileStream fs raw = File.Open(_outputFileName, FileMode.Create, FileAccess.ReadWrite )) - /// { - /// using (var output= new ZipOutputStream(fs)) - /// { - /// output.Password = "VerySecret!"; - /// output.Encryption = EncryptionAlgorithm.WinZipAes256; - /// output.PutNextEntry("entry1.txt"); - /// byte[] buffer= System.Text.Encoding.ASCII.GetBytes("This is the content for entry #1."); - /// output.Write(buffer,0,buffer.Length); - /// output.PutNextEntry("entry2.txt"); // this will be zero length - /// output.PutNextEntry("entry3.txt"); - /// buffer= System.Text.Encoding.ASCII.GetBytes("This is the content for entry #3."); - /// output.Write(buffer,0,buffer.Length); - /// } - /// } - /// } - /// - /// - /// - /// - /// The name of the entry to be added, including any path to be used - /// within the zip file. - /// - /// - /// - /// The ZipEntry created. - /// - /// - public ZipEntry PutNextEntry(String entryName) - { - if (String.IsNullOrEmpty(entryName)) - throw new ArgumentNullException("entryName"); - - if (_disposed) - { - _exceptionPending = true; - throw new System.InvalidOperationException("The stream has been closed."); - } - - _FinishCurrentEntry(); - _currentEntry = ZipEntry.CreateForZipOutputStream(entryName); - _currentEntry._container = new ZipContainer(this); - _currentEntry._BitField |= 0x0008; // workitem 8932 - _currentEntry.SetEntryTimes(DateTime.Now, DateTime.Now, DateTime.Now); - _currentEntry.CompressionLevel = this.CompressionLevel; - _currentEntry.CompressionMethod = this.CompressionMethod; - _currentEntry.Password = _password; // workitem 13909 - _currentEntry.Encryption = this.Encryption; - // workitem 12634 - _currentEntry.AlternateEncoding = this.AlternateEncoding; - _currentEntry.AlternateEncodingUsage = this.AlternateEncodingUsage; - - if (entryName.EndsWith("/")) _currentEntry.MarkAsDirectory(); - - _currentEntry.EmitTimesInWindowsFormatWhenSaving = ((_timestamp & ZipEntryTimestamp.Windows) != 0); - _currentEntry.EmitTimesInUnixFormatWhenSaving = ((_timestamp & ZipEntryTimestamp.Unix) != 0); - InsureUniqueEntry(_currentEntry); - _needToWriteEntryHeader = true; - - return _currentEntry; - } - - - - private void _InitiateCurrentEntry(bool finishing) - { - // If finishing==true, this means we're initiating the entry at the time of - // Close() or PutNextEntry(). If this happens, it means no data was written - // for the entry - Write() was never called. (The usual case us to call - // _InitiateCurrentEntry(bool) from within Write().) If finishing==true, - // the entry could be either a zero-byte file or a directory. - - _entriesWritten.Add(_currentEntry.FileName,_currentEntry); - _entryCount++; // could use _entriesWritten.Count, but I don't want to incur - // the cost. - - if (_entryCount > 65534 && _zip64 == Zip64Option.Never) - { - _exceptionPending = true; - throw new System.InvalidOperationException("Too many entries. Consider setting ZipOutputStream.EnableZip64."); - } - - // Write out the header. - // - // If finishing, and encryption is in use, then we don't want to emit the - // normal encryption header. Signal that with a cycle=99 to turn off - // encryption for zero-byte entries or directories. - // - // If finishing, then we know the stream length is zero. Else, unknown - // stream length. Passing stream length == 0 allows an optimization so as - // not to setup an encryption or deflation stream, when stream length is - // zero. - - _currentEntry.WriteHeader(_outputStream, finishing ? 99 : 0); - _currentEntry.StoreRelativeOffset(); - - if (!_currentEntry.IsDirectory) - { - _currentEntry.WriteSecurityMetadata(_outputStream); - _currentEntry.PrepOutputStream(_outputStream, - finishing ? 0 : -1, - out _outputCounter, - out _encryptor, - out _deflater, - out _entryOutputStream); - } - _needToWriteEntryHeader = false; - } - - - - private void _FinishCurrentEntry() - { - if (_currentEntry != null) - { - if (_needToWriteEntryHeader) - _InitiateCurrentEntry(true); // an empty entry - no writes - - _currentEntry.FinishOutputStream(_outputStream, _outputCounter, _encryptor, _deflater, _entryOutputStream); - _currentEntry.PostProcessOutput(_outputStream); - // workitem 12964 - if (_currentEntry.OutputUsedZip64!=null) - _anyEntriesUsedZip64 |= _currentEntry.OutputUsedZip64.Value; - - // reset all the streams - _outputCounter = null; _encryptor = _deflater = null; _entryOutputStream = null; - } - } - - - - /// - /// Dispose the stream - /// - /// - /// - /// - /// This method writes the Zip Central directory, then closes the stream. The - /// application must call Dispose() (or Close) in order to produce a valid zip file. - /// - /// - /// - /// Typically the application will call Dispose() implicitly, via a using - /// statement in C#, or a Using statement in VB. - /// - /// - /// - /// - /// set this to true, always. - protected override void Dispose(bool disposing) - { - if (_disposed) return; - - if (disposing) // not called from finalizer - { - // handle pending exceptions - if (!_exceptionPending) - { - _FinishCurrentEntry(); - _directoryNeededZip64 = ZipOutput.WriteCentralDirectoryStructure(_outputStream, - _entriesWritten.Values, - 1, // _numberOfSegmentsForMostRecentSave, - _zip64, - Comment, - new ZipContainer(this)); - Stream wrappedStream = null; - CountingStream cs = _outputStream as CountingStream; - if (cs != null) - { - wrappedStream = cs.WrappedStream; -#if NETCF - cs.Close(); -#else - cs.Dispose(); -#endif - } - else - { - wrappedStream = _outputStream; - } - - if (!_leaveUnderlyingStreamOpen) - { -#if NETCF - wrappedStream.Close(); -#else - wrappedStream.Dispose(); -#endif - } - _outputStream = null; - } - } - _disposed = true; - } - - - - /// - /// Always returns false. - /// - public override bool CanRead { get { return false; } } - - /// - /// Always returns false. - /// - public override bool CanSeek { get { return false; } } - - /// - /// Always returns true. - /// - public override bool CanWrite { get { return true; } } - - /// - /// Always returns a NotSupportedException. - /// - public override long Length { get { throw new NotSupportedException(); } } - - /// - /// Setting this property always returns a NotSupportedException. Getting it - /// returns the value of the Position on the underlying stream. - /// - public override long Position - { - get { return _outputStream.Position; } - set { throw new NotSupportedException(); } - } - - /// - /// This is a no-op. - /// - public override void Flush() { } - - /// - /// This method always throws a NotSupportedException. - /// - /// ignored - /// ignored - /// ignored - /// nothing - public override int Read(byte[] buffer, int offset, int count) - { - throw new NotSupportedException("Read"); - } - - /// - /// This method always throws a NotSupportedException. - /// - /// ignored - /// ignored - /// nothing - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotSupportedException("Seek"); - } - - /// - /// This method always throws a NotSupportedException. - /// - /// ignored - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - - private EncryptionAlgorithm _encryption; - private ZipEntryTimestamp _timestamp; - internal String _password; - private String _comment; - private Stream _outputStream; - private ZipEntry _currentEntry; - internal Zip64Option _zip64; - private Dictionary _entriesWritten; - private int _entryCount; - private ZipOption _alternateEncodingUsage = ZipOption.Never; - private System.Text.Encoding _alternateEncoding - = System.Text.Encoding.GetEncoding("IBM437"); // default = IBM437 - - private bool _leaveUnderlyingStreamOpen; - private bool _disposed; - private bool _exceptionPending; // **see note below - private bool _anyEntriesUsedZip64, _directoryNeededZip64; - private CountingStream _outputCounter; - private Stream _encryptor; - private Stream _deflater; - private Ionic.Crc.CrcCalculatorStream _entryOutputStream; - private bool _needToWriteEntryHeader; - private string _name; - private bool _DontIgnoreCase; -#if !NETCF - internal Ionic.Zlib.ParallelDeflateOutputStream ParallelDeflater; - private long _ParallelDeflateThreshold; - private int _maxBufferPairs = 16; -#endif - - // **Note regarding exceptions: - - // When ZipOutputStream is employed within a using clause, which - // is the typical scenario, and an exception is thrown within - // the scope of the using, Close()/Dispose() is invoked - // implicitly before processing the initial exception. In that - // case, _exceptionPending is true, and we don't want to try to - // write anything in the Close/Dispose logic. Doing so can - // cause additional exceptions that mask the original one. So, - // the _exceptionPending flag is used to track that, and to - // allow the original exception to be propagated to the - // application without extra "noise." - - } - - - - internal class ZipContainer - { - private ZipFile _zf; - private ZipOutputStream _zos; - private ZipInputStream _zis; - - public ZipContainer(Object o) - { - _zf = (o as ZipFile); - _zos = (o as ZipOutputStream); - _zis = (o as ZipInputStream); - } - - public ZipFile ZipFile - { - get { return _zf; } - } - - public ZipOutputStream ZipOutputStream - { - get { return _zos; } - } - - public string Name - { - get - { - if (_zf != null) return _zf.Name; - if (_zis != null) throw new NotSupportedException(); - return _zos.Name; - } - } - - public string Password - { - get - { - if (_zf != null) return _zf._Password; - if (_zis != null) return _zis._Password; - return _zos._password; - } - } - - public Zip64Option Zip64 - { - get - { - if (_zf != null) return _zf._zip64; - if (_zis != null) throw new NotSupportedException(); - return _zos._zip64; - } - } - - public int BufferSize - { - get - { - if (_zf != null) return _zf.BufferSize; - if (_zis != null) throw new NotSupportedException(); - return 0; - } - } - -#if !NETCF - public Ionic.Zlib.ParallelDeflateOutputStream ParallelDeflater - { - get - { - if (_zf != null) return _zf.ParallelDeflater; - if (_zis != null) return null; - return _zos.ParallelDeflater; - } - set - { - if (_zf != null) _zf.ParallelDeflater = value; - else if (_zos != null) _zos.ParallelDeflater = value; - } - } - - public long ParallelDeflateThreshold - { - get - { - if (_zf != null) return _zf.ParallelDeflateThreshold; - return _zos.ParallelDeflateThreshold; - } - } - public int ParallelDeflateMaxBufferPairs - { - get - { - if (_zf != null) return _zf.ParallelDeflateMaxBufferPairs; - return _zos.ParallelDeflateMaxBufferPairs; - } - } -#endif - - public int CodecBufferSize - { - get - { - if (_zf != null) return _zf.CodecBufferSize; - if (_zis != null) return _zis.CodecBufferSize; - return _zos.CodecBufferSize; - } - } - - public Ionic.Zlib.CompressionStrategy Strategy - { - get - { - if (_zf != null) return _zf.Strategy; - return _zos.Strategy; - } - } - - public Zip64Option UseZip64WhenSaving - { - get - { - if (_zf != null) return _zf.UseZip64WhenSaving; - return _zos.EnableZip64; - } - } - - public System.Text.Encoding AlternateEncoding - { - get - { - if (_zf != null) return _zf.AlternateEncoding; - if (_zos!=null) return _zos.AlternateEncoding; - return null; - } - } - public System.Text.Encoding DefaultEncoding - { - get - { - if (_zf != null) return ZipFile.DefaultEncoding; - if (_zos!=null) return ZipOutputStream.DefaultEncoding; - return null; - } - } - public ZipOption AlternateEncodingUsage - { - get - { - if (_zf != null) return _zf.AlternateEncodingUsage; - if (_zos!=null) return _zos.AlternateEncodingUsage; - return ZipOption.Never; // n/a - } - } - - public Stream ReadStream - { - get - { - if (_zf != null) return _zf.ReadStream; - return _zis.ReadStream; - } - } - } - -} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipSegmentedStream.cs b/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipSegmentedStream.cs deleted file mode 100644 index 7fe4f116..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zip/ZipSegmentedStream.cs +++ /dev/null @@ -1,571 +0,0 @@ -// ZipSegmentedStream.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-13 22:25:45> -// -// ------------------------------------------------------------------ -// -// This module defines logic for zip streams that span disk files. -// -// ------------------------------------------------------------------ - - -using System; -using System.Collections.Generic; -using System.IO; - -namespace Ionic.Zip -{ - internal class ZipSegmentedStream : System.IO.Stream - { - enum RwMode - { - None = 0, - ReadOnly = 1, - Write = 2, - //Update = 3 - } - - private RwMode rwMode; - private bool _exceptionPending; // **see note below - private string _baseName; - private string _baseDir; - //private bool _isDisposed; - private string _currentName; - private string _currentTempName; - private uint _currentDiskNumber; - private uint _maxDiskNumber; - private int _maxSegmentSize; - private System.IO.Stream _innerStream; - - // **Note regarding exceptions: - // - // When ZipSegmentedStream is employed within a using clause, - // which is the typical scenario, and an exception is thrown - // within the scope of the using, Dispose() is invoked - // implicitly before processing the initial exception. If that - // happens, this class sets _exceptionPending to true, and then - // within the Dispose(bool), takes special action as - // appropriate. Need to be careful: any additional exceptions - // will mask the original one. - - private ZipSegmentedStream() : base() - { - _exceptionPending = false; - } - - public static ZipSegmentedStream ForReading(string name, - uint initialDiskNumber, - uint maxDiskNumber) - { - ZipSegmentedStream zss = new ZipSegmentedStream() - { - rwMode = RwMode.ReadOnly, - CurrentSegment = initialDiskNumber, - _maxDiskNumber = maxDiskNumber, - _baseName = name, - }; - - // Console.WriteLine("ZSS: ForReading ({0})", - // Path.GetFileName(zss.CurrentName)); - - zss._SetReadStream(); - - return zss; - } - - - public static ZipSegmentedStream ForWriting(string name, int maxSegmentSize) - { - ZipSegmentedStream zss = new ZipSegmentedStream() - { - rwMode = RwMode.Write, - CurrentSegment = 0, - _baseName = name, - _maxSegmentSize = maxSegmentSize, - _baseDir = Path.GetDirectoryName(name) - }; - - // workitem 9522 - if (zss._baseDir=="") zss._baseDir="."; - - zss._SetWriteStream(0); - - // Console.WriteLine("ZSS: ForWriting ({0})", - // Path.GetFileName(zss.CurrentName)); - - return zss; - } - - - /// - /// Sort-of like a factory method, ForUpdate is used only when - /// the application needs to update the zip entry metadata for - /// a segmented zip file, when the starting segment is earlier - /// than the ending segment, for a particular entry. - /// - /// - /// - /// The update is always contiguous, never rolls over. As a - /// result, this method doesn't need to return a ZSS; it can - /// simply return a FileStream. That's why it's "sort of" - /// like a Factory method. - /// - /// - /// Caller must Close/Dispose the stream object returned by - /// this method. - /// - /// - public static Stream ForUpdate(string name, uint diskNumber) - { - if (diskNumber >= 99) - throw new ArgumentOutOfRangeException("diskNumber"); - - string fname = - String.Format("{0}.z{1:D2}", - Path.Combine(Path.GetDirectoryName(name), - Path.GetFileNameWithoutExtension(name)), - diskNumber + 1); - - // Console.WriteLine("ZSS: ForUpdate ({0})", - // Path.GetFileName(fname)); - - // This class assumes that the update will not expand the - // size of the segment. Update is used only for an in-place - // update of zip metadata. It never will try to write beyond - // the end of a segment. - - return File.Open(fname, - FileMode.Open, - FileAccess.ReadWrite, - FileShare.None); - } - - public bool ContiguousWrite - { - get; - set; - } - - - public UInt32 CurrentSegment - { - get - { - return _currentDiskNumber; - } - private set - { - _currentDiskNumber = value; - _currentName = null; // it will get updated next time referenced - } - } - - /// - /// Name of the filesystem file corresponding to the current segment. - /// - /// - /// - /// The name is not always the name currently being used in the - /// filesystem. When rwMode is RwMode.Write, the filesystem file has a - /// temporary name until the stream is closed or until the next segment is - /// started. - /// - /// - public String CurrentName - { - get - { - if (_currentName==null) - _currentName = _NameForSegment(CurrentSegment); - - return _currentName; - } - } - - - public String CurrentTempName - { - get - { - return _currentTempName; - } - } - - private string _NameForSegment(uint diskNumber) - { - if (diskNumber >= 99) - { - _exceptionPending = true; - throw new OverflowException("The number of zip segments would exceed 99."); - } - - return String.Format("{0}.z{1:D2}", - Path.Combine(Path.GetDirectoryName(_baseName), - Path.GetFileNameWithoutExtension(_baseName)), - diskNumber + 1); - } - - - // Returns the segment that WILL be current if writing - // a block of the given length. - // This isn't exactly true. It could roll over beyond - // this number. - public UInt32 ComputeSegment(int length) - { - if (_innerStream.Position + length > _maxSegmentSize) - // the block will go AT LEAST into the next segment - return CurrentSegment + 1; - - // it will fit in the current segment - return CurrentSegment; - } - - - public override String ToString() - { - return String.Format("{0}[{1}][{2}], pos=0x{3:X})", - "ZipSegmentedStream", CurrentName, - rwMode.ToString(), - this.Position); - } - - - private void _SetReadStream() - { - if (_innerStream != null) - { -#if NETCF - _innerStream.Close(); -#else - _innerStream.Dispose(); -#endif - } - - if (CurrentSegment + 1 == _maxDiskNumber) - _currentName = _baseName; - - // Console.WriteLine("ZSS: SRS ({0})", - // Path.GetFileName(CurrentName)); - - _innerStream = File.OpenRead(CurrentName); - } - - - /// - /// Read from the stream - /// - /// the buffer to read - /// the offset at which to start - /// the number of bytes to read - /// the number of bytes actually read - public override int Read(byte[] buffer, int offset, int count) - { - if (rwMode != RwMode.ReadOnly) - { - _exceptionPending = true; - throw new InvalidOperationException("Stream Error: Cannot Read."); - } - - int r = _innerStream.Read(buffer, offset, count); - int r1 = r; - - while (r1 != count) - { - if (_innerStream.Position != _innerStream.Length) - { - _exceptionPending = true; - throw new ZipException(String.Format("Read error in file {0}", CurrentName)); - - } - - if (CurrentSegment + 1 == _maxDiskNumber) - return r; // no more to read - - CurrentSegment++; - _SetReadStream(); - offset += r1; - count -= r1; - r1 = _innerStream.Read(buffer, offset, count); - r += r1; - } - return r; - } - - - - private void _SetWriteStream(uint increment) - { - if (_innerStream != null) - { -#if NETCF - _innerStream.Close(); -#else - _innerStream.Dispose(); -#endif - if (File.Exists(CurrentName)) - File.Delete(CurrentName); - File.Move(_currentTempName, CurrentName); - // Console.WriteLine("ZSS: SWS close ({0})", - // Path.GetFileName(CurrentName)); - } - - if (increment > 0) - CurrentSegment += increment; - - SharedUtilities.CreateAndOpenUniqueTempFile(_baseDir, - out _innerStream, - out _currentTempName); - - // Console.WriteLine("ZSS: SWS open ({0})", - // Path.GetFileName(_currentTempName)); - - if (CurrentSegment == 0) - _innerStream.Write(BitConverter.GetBytes(ZipConstants.SplitArchiveSignature), 0, 4); - } - - - /// - /// Write to the stream. - /// - /// the buffer from which to write - /// the offset at which to start writing - /// the number of bytes to write - public override void Write(byte[] buffer, int offset, int count) - { - if (rwMode != RwMode.Write) - { - _exceptionPending = true; - throw new InvalidOperationException("Stream Error: Cannot Write."); - } - - - if (ContiguousWrite) - { - // enough space for a contiguous write? - if (_innerStream.Position + count > _maxSegmentSize) - _SetWriteStream(1); - } - else - { - while (_innerStream.Position + count > _maxSegmentSize) - { - int c = unchecked(_maxSegmentSize - (int)_innerStream.Position); - _innerStream.Write(buffer, offset, c); - _SetWriteStream(1); - count -= c; - offset += c; - } - } - - _innerStream.Write(buffer, offset, count); - } - - - public long TruncateBackward(uint diskNumber, long offset) - { - // Console.WriteLine("***ZSS.Trunc to disk {0}", diskNumber); - // Console.WriteLine("***ZSS.Trunc: current disk {0}", CurrentSegment); - if (diskNumber >= 99) - throw new ArgumentOutOfRangeException("diskNumber"); - - if (rwMode != RwMode.Write) - { - _exceptionPending = true; - throw new ZipException("bad state."); - } - - // Seek back in the segmented stream to a (maybe) prior segment. - - // Check if it is the same segment. If it is, very simple. - if (diskNumber == CurrentSegment) - { - var x =_innerStream.Seek(offset, SeekOrigin.Begin); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(_innerStream); - return x; - } - - // Seeking back to a prior segment. - // The current segment and any intervening segments must be removed. - // First, close the current segment, and then remove it. - if (_innerStream != null) - { -#if NETCF - _innerStream.Close(); -#else - _innerStream.Dispose(); -#endif - if (File.Exists(_currentTempName)) - File.Delete(_currentTempName); - } - - // Now, remove intervening segments. - for (uint j= CurrentSegment-1; j > diskNumber; j--) - { - string s = _NameForSegment(j); - // Console.WriteLine("***ZSS.Trunc: removing file {0}", s); - if (File.Exists(s)) - File.Delete(s); - } - - // now, open the desired segment. It must exist. - CurrentSegment = diskNumber; - - // get a new temp file, try 3 times: - for (int i = 0; i < 3; i++) - { - try - { - _currentTempName = SharedUtilities.InternalGetTempFileName(); - // move the .z0x file back to a temp name - File.Move(CurrentName, _currentTempName); - break; // workitem 12403 - } - catch(IOException) - { - if (i == 2) throw; - } - } - - // open it - _innerStream = new FileStream(_currentTempName, FileMode.Open); - - var r = _innerStream.Seek(offset, SeekOrigin.Begin); - - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(_innerStream); - - return r; - } - - - - public override bool CanRead - { - get - { - return (rwMode == RwMode.ReadOnly && - (_innerStream != null) && - _innerStream.CanRead); - } - } - - - public override bool CanSeek - { - get - { - return (_innerStream != null) && - _innerStream.CanSeek; - } - } - - - public override bool CanWrite - { - get - { - return (rwMode == RwMode.Write) && - (_innerStream != null) && - _innerStream.CanWrite; - } - } - - public override void Flush() - { - _innerStream.Flush(); - } - - public override long Length - { - get - { - return _innerStream.Length; - } - } - - public override long Position - { - get { return _innerStream.Position; } - set { _innerStream.Position = value; } - } - - public override long Seek(long offset, System.IO.SeekOrigin origin) - { - var x = _innerStream.Seek(offset, origin); - // workitem 10178 - Ionic.Zip.SharedUtilities.Workaround_Ladybug318918(_innerStream); - return x; - } - - public override void SetLength(long value) - { - if (rwMode != RwMode.Write) - { - _exceptionPending = true; - throw new InvalidOperationException(); - } - _innerStream.SetLength(value); - } - - - protected override void Dispose(bool disposing) - { - // this gets called by Stream.Close() - - // if (_isDisposed) return; - // _isDisposed = true; - //Console.WriteLine("Dispose (mode={0})\n", rwMode.ToString()); - - try - { - if (_innerStream != null) - { -#if NETCF - _innerStream.Close(); -#else - _innerStream.Dispose(); -#endif - //_innerStream = null; - if (rwMode == RwMode.Write) - { - if (_exceptionPending) - { - // possibly could try to clean up all the - // temp files created so far... - } - else - { - // // move the final temp file to the .zNN name - // if (File.Exists(CurrentName)) - // File.Delete(CurrentName); - // if (File.Exists(_currentTempName)) - // File.Move(_currentTempName, CurrentName); - } - } - } - } - finally - { - base.Dispose(disposing); - } - } - - } - -} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/Compression/Zlib.cs b/MinecraftClient/Protocol/Handlers/Compression/Zlib.cs deleted file mode 100644 index 8019be80..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/Zlib.cs +++ /dev/null @@ -1,548 +0,0 @@ -// Zlib.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2009-2011 Dino Chiesa and Microsoft Corporation. -// 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: <2011-August-03 19:52:28> -// -// ------------------------------------------------------------------ -// -// This module defines classes for ZLIB compression and -// decompression. This code is derived from the jzlib implementation of -// zlib, but significantly modified. The object model is not the same, -// and many of the behaviors are new or different. Nonetheless, in -// keeping with the license for jzlib, the copyright to that code is -// included below. -// -// ------------------------------------------------------------------ -// -// The following notice applies to jzlib: -// -// Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in -// the documentation and/or other materials provided with the distribution. -// -// 3. The names of the authors may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -// INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// ----------------------------------------------------------------------- -// -// jzlib is based on zlib-1.1.3. -// -// The following notice applies to zlib: -// -// ----------------------------------------------------------------------- -// -// Copyright (C) 1995-2004 Jean-loup Gailly and Mark Adler -// -// The ZLIB software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. -// -// Jean-loup Gailly jloup@gzip.org -// Mark Adler madler@alumni.caltech.edu -// -// ----------------------------------------------------------------------- - - - -using System; -using System.Runtime.CompilerServices; -using Interop=System.Runtime.InteropServices; - -namespace Ionic.Zlib -{ - - /// - /// Describes how to flush the current deflate operation. - /// - /// - /// The different FlushType values are useful when using a Deflate in a streaming application. - /// - public enum FlushType - { - /// No flush at all. - None = 0, - - /// Closes the current block, but doesn't flush it to - /// the output. Used internally only in hypothetical - /// scenarios. This was supposed to be removed by Zlib, but it is - /// still in use in some edge cases. - /// - Partial, - - /// - /// Use this during compression to specify that all pending output should be - /// flushed to the output buffer and the output should be aligned on a byte - /// boundary. You might use this in a streaming communication scenario, so that - /// the decompressor can get all input data available so far. When using this - /// with a ZlibCodec, AvailableBytesIn will be zero after the call if - /// enough output space has been provided before the call. Flushing will - /// degrade compression and so it should be used only when necessary. - /// - Sync, - - /// - /// Use this during compression to specify that all output should be flushed, as - /// with FlushType.Sync, but also, the compression state should be reset - /// so that decompression can restart from this point if previous compressed - /// data has been damaged or if random access is desired. Using - /// FlushType.Full too often can significantly degrade the compression. - /// - Full, - - /// Signals the end of the compression/decompression stream. - Finish, - } - - - /// - /// The compression level to be used when using a DeflateStream or ZlibStream with CompressionMode.Compress. - /// - public enum CompressionLevel - { - /// - /// None means that the data will be simply stored, with no change at all. - /// If you are producing ZIPs for use on Mac OSX, be aware that archives produced with CompressionLevel.None - /// cannot be opened with the default zip reader. Use a different CompressionLevel. - /// - None= 0, - /// - /// Same as None. - /// - Level0 = 0, - - /// - /// The fastest but least effective compression. - /// - BestSpeed = 1, - - /// - /// A synonym for BestSpeed. - /// - Level1 = 1, - - /// - /// A little slower, but better, than level 1. - /// - Level2 = 2, - - /// - /// A little slower, but better, than level 2. - /// - Level3 = 3, - - /// - /// A little slower, but better, than level 3. - /// - Level4 = 4, - - /// - /// A little slower than level 4, but with better compression. - /// - Level5 = 5, - - /// - /// The default compression level, with a good balance of speed and compression efficiency. - /// - Default = 6, - /// - /// A synonym for Default. - /// - Level6 = 6, - - /// - /// Pretty good compression! - /// - Level7 = 7, - - /// - /// Better compression than Level7! - /// - Level8 = 8, - - /// - /// The "best" compression, where best means greatest reduction in size of the input data stream. - /// This is also the slowest compression. - /// - BestCompression = 9, - - /// - /// A synonym for BestCompression. - /// - Level9 = 9, - } - - /// - /// Describes options for how the compression algorithm is executed. Different strategies - /// work better on different sorts of data. The strategy parameter can affect the compression - /// ratio and the speed of compression but not the correctness of the compresssion. - /// - public enum CompressionStrategy - { - /// - /// The default strategy is probably the best for normal data. - /// - Default = 0, - - /// - /// The Filtered strategy is intended to be used most effectively with data produced by a - /// filter or predictor. By this definition, filtered data consists mostly of small - /// values with a somewhat random distribution. In this case, the compression algorithm - /// is tuned to compress them better. The effect of Filtered is to force more Huffman - /// coding and less string matching; it is a half-step between Default and HuffmanOnly. - /// - Filtered = 1, - - /// - /// Using HuffmanOnly will force the compressor to do Huffman encoding only, with no - /// string matching. - /// - HuffmanOnly = 2, - } - - - /// - /// An enum to specify the direction of transcoding - whether to compress or decompress. - /// - public enum CompressionMode - { - /// - /// Used to specify that the stream should compress the data. - /// - Compress= 0, - /// - /// Used to specify that the stream should decompress the data. - /// - Decompress = 1, - } - - - /// - /// A general purpose exception class for exceptions in the Zlib library. - /// - [Interop.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d0000E")] - public class ZlibException : System.Exception - { - /// - /// The ZlibException class captures exception information generated - /// by the Zlib library. - /// - public ZlibException() - : base() - { - } - - /// - /// This ctor collects a message attached to the exception. - /// - /// the message for the exception. - public ZlibException(System.String s) - : base(s) - { - } - } - - - internal class SharedUtils - { - /// - /// Performs an unsigned bitwise right shift with the specified number - /// - /// Number to operate on - /// Ammount of bits to shift - /// The resulting number from the shift operation - public static int URShift(int number, int bits) - { - return (int)((uint)number >> bits); - } - -#if NOT - /// - /// Performs an unsigned bitwise right shift with the specified number - /// - /// Number to operate on - /// Ammount of bits to shift - /// The resulting number from the shift operation - public static long URShift(long number, int bits) - { - return (long) ((UInt64)number >> bits); - } -#endif - - /// - /// Reads a number of characters from the current source TextReader and writes - /// the data to the target array at the specified index. - /// - /// - /// The source TextReader to read from - /// Contains the array of characteres read from the source TextReader. - /// The starting index of the target array. - /// The maximum number of characters to read from the source TextReader. - /// - /// - /// The number of characters read. The number will be less than or equal to - /// count depending on the data available in the source TextReader. Returns -1 - /// if the end of the stream is reached. - /// - public static System.Int32 ReadInput(System.IO.TextReader sourceTextReader, byte[] target, int start, int count) - { - // Returns 0 bytes if not enough space in target - if (target.Length == 0) return 0; - - char[] charArray = new char[target.Length]; - int bytesRead = sourceTextReader.Read(charArray, start, count); - - // Returns -1 if EOF - if (bytesRead == 0) return -1; - - for (int index = start; index < start + bytesRead; index++) - target[index] = (byte)charArray[index]; - - return bytesRead; - } - - - internal static byte[] ToByteArray(System.String sourceString) - { - return System.Text.UTF8Encoding.UTF8.GetBytes(sourceString); - } - - - internal static char[] ToCharArray(byte[] byteArray) - { - return System.Text.UTF8Encoding.UTF8.GetChars(byteArray); - } - } - - internal static class InternalConstants - { - internal static readonly int MAX_BITS = 15; - internal static readonly int BL_CODES = 19; - internal static readonly int D_CODES = 30; - internal static readonly int LITERALS = 256; - internal static readonly int LENGTH_CODES = 29; - internal static readonly int L_CODES = (LITERALS + 1 + LENGTH_CODES); - - // Bit length codes must not exceed MAX_BL_BITS bits - internal static readonly int MAX_BL_BITS = 7; - - // repeat previous bit length 3-6 times (2 bits of repeat count) - internal static readonly int REP_3_6 = 16; - - // repeat a zero length 3-10 times (3 bits of repeat count) - internal static readonly int REPZ_3_10 = 17; - - // repeat a zero length 11-138 times (7 bits of repeat count) - internal static readonly int REPZ_11_138 = 18; - - } - - internal sealed class StaticTree - { - internal static readonly short[] lengthAndLiteralsTreeCodes = new short[] { - 12, 8, 140, 8, 76, 8, 204, 8, 44, 8, 172, 8, 108, 8, 236, 8, - 28, 8, 156, 8, 92, 8, 220, 8, 60, 8, 188, 8, 124, 8, 252, 8, - 2, 8, 130, 8, 66, 8, 194, 8, 34, 8, 162, 8, 98, 8, 226, 8, - 18, 8, 146, 8, 82, 8, 210, 8, 50, 8, 178, 8, 114, 8, 242, 8, - 10, 8, 138, 8, 74, 8, 202, 8, 42, 8, 170, 8, 106, 8, 234, 8, - 26, 8, 154, 8, 90, 8, 218, 8, 58, 8, 186, 8, 122, 8, 250, 8, - 6, 8, 134, 8, 70, 8, 198, 8, 38, 8, 166, 8, 102, 8, 230, 8, - 22, 8, 150, 8, 86, 8, 214, 8, 54, 8, 182, 8, 118, 8, 246, 8, - 14, 8, 142, 8, 78, 8, 206, 8, 46, 8, 174, 8, 110, 8, 238, 8, - 30, 8, 158, 8, 94, 8, 222, 8, 62, 8, 190, 8, 126, 8, 254, 8, - 1, 8, 129, 8, 65, 8, 193, 8, 33, 8, 161, 8, 97, 8, 225, 8, - 17, 8, 145, 8, 81, 8, 209, 8, 49, 8, 177, 8, 113, 8, 241, 8, - 9, 8, 137, 8, 73, 8, 201, 8, 41, 8, 169, 8, 105, 8, 233, 8, - 25, 8, 153, 8, 89, 8, 217, 8, 57, 8, 185, 8, 121, 8, 249, 8, - 5, 8, 133, 8, 69, 8, 197, 8, 37, 8, 165, 8, 101, 8, 229, 8, - 21, 8, 149, 8, 85, 8, 213, 8, 53, 8, 181, 8, 117, 8, 245, 8, - 13, 8, 141, 8, 77, 8, 205, 8, 45, 8, 173, 8, 109, 8, 237, 8, - 29, 8, 157, 8, 93, 8, 221, 8, 61, 8, 189, 8, 125, 8, 253, 8, - 19, 9, 275, 9, 147, 9, 403, 9, 83, 9, 339, 9, 211, 9, 467, 9, - 51, 9, 307, 9, 179, 9, 435, 9, 115, 9, 371, 9, 243, 9, 499, 9, - 11, 9, 267, 9, 139, 9, 395, 9, 75, 9, 331, 9, 203, 9, 459, 9, - 43, 9, 299, 9, 171, 9, 427, 9, 107, 9, 363, 9, 235, 9, 491, 9, - 27, 9, 283, 9, 155, 9, 411, 9, 91, 9, 347, 9, 219, 9, 475, 9, - 59, 9, 315, 9, 187, 9, 443, 9, 123, 9, 379, 9, 251, 9, 507, 9, - 7, 9, 263, 9, 135, 9, 391, 9, 71, 9, 327, 9, 199, 9, 455, 9, - 39, 9, 295, 9, 167, 9, 423, 9, 103, 9, 359, 9, 231, 9, 487, 9, - 23, 9, 279, 9, 151, 9, 407, 9, 87, 9, 343, 9, 215, 9, 471, 9, - 55, 9, 311, 9, 183, 9, 439, 9, 119, 9, 375, 9, 247, 9, 503, 9, - 15, 9, 271, 9, 143, 9, 399, 9, 79, 9, 335, 9, 207, 9, 463, 9, - 47, 9, 303, 9, 175, 9, 431, 9, 111, 9, 367, 9, 239, 9, 495, 9, - 31, 9, 287, 9, 159, 9, 415, 9, 95, 9, 351, 9, 223, 9, 479, 9, - 63, 9, 319, 9, 191, 9, 447, 9, 127, 9, 383, 9, 255, 9, 511, 9, - 0, 7, 64, 7, 32, 7, 96, 7, 16, 7, 80, 7, 48, 7, 112, 7, - 8, 7, 72, 7, 40, 7, 104, 7, 24, 7, 88, 7, 56, 7, 120, 7, - 4, 7, 68, 7, 36, 7, 100, 7, 20, 7, 84, 7, 52, 7, 116, 7, - 3, 8, 131, 8, 67, 8, 195, 8, 35, 8, 163, 8, 99, 8, 227, 8 - }; - - internal static readonly short[] distTreeCodes = new short[] { - 0, 5, 16, 5, 8, 5, 24, 5, 4, 5, 20, 5, 12, 5, 28, 5, - 2, 5, 18, 5, 10, 5, 26, 5, 6, 5, 22, 5, 14, 5, 30, 5, - 1, 5, 17, 5, 9, 5, 25, 5, 5, 5, 21, 5, 13, 5, 29, 5, - 3, 5, 19, 5, 11, 5, 27, 5, 7, 5, 23, 5 }; - - internal static readonly StaticTree Literals; - internal static readonly StaticTree Distances; - internal static readonly StaticTree BitLengths; - - internal short[] treeCodes; // static tree or null - internal int[] extraBits; // extra bits for each code or null - internal int extraBase; // base index for extra_bits - internal int elems; // max number of elements in the tree - internal int maxLength; // max bit length for the codes - - private StaticTree(short[] treeCodes, int[] extraBits, int extraBase, int elems, int maxLength) - { - this.treeCodes = treeCodes; - this.extraBits = extraBits; - this.extraBase = extraBase; - this.elems = elems; - this.maxLength = maxLength; - } - static StaticTree() - { - Literals = new StaticTree(lengthAndLiteralsTreeCodes, Tree.ExtraLengthBits, InternalConstants.LITERALS + 1, InternalConstants.L_CODES, InternalConstants.MAX_BITS); - Distances = new StaticTree(distTreeCodes, Tree.ExtraDistanceBits, 0, InternalConstants.D_CODES, InternalConstants.MAX_BITS); - BitLengths = new StaticTree(null, Tree.extra_blbits, 0, InternalConstants.BL_CODES, InternalConstants.MAX_BL_BITS); - } - } - - - - /// - /// Computes an Adler-32 checksum. - /// - /// - /// The Adler checksum is similar to a CRC checksum, but faster to compute, though less - /// reliable. It is used in producing RFC1950 compressed streams. The Adler checksum - /// is a required part of the "ZLIB" standard. Applications will almost never need to - /// use this class directly. - /// - /// - /// - public sealed class Adler - { - // largest prime smaller than 65536 - private static readonly uint BASE = 65521; - // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 - private static readonly int NMAX = 5552; - - -#pragma warning disable 3001 -#pragma warning disable 3002 - - /// - /// Calculates the Adler32 checksum. - /// - /// - /// - /// This is used within ZLIB. You probably don't need to use this directly. - /// - /// - /// - /// To compute an Adler32 checksum on a byte array: - /// - /// var adler = Adler.Adler32(0, null, 0, 0); - /// adler = Adler.Adler32(adler, buffer, index, length); - /// - /// - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - public static uint Adler32(uint adler, byte[] buf, int index, int len) - { - if (buf == null) - return 1; - - uint s1 = (uint) (adler & 0xffff); - uint s2 = (uint) ((adler >> 16) & 0xffff); - - while (len > 0) - { - int k = len < NMAX ? len : NMAX; - len -= k; - while (k >= 16) - { - //s1 += (buf[index++] & 0xff); s2 += s1; - s1 += buf[index++]; s2 += s1; - s1 += buf[index++]; s2 += s1; - s1 += buf[index++]; s2 += s1; - s1 += buf[index++]; s2 += s1; - s1 += buf[index++]; s2 += s1; - s1 += buf[index++]; s2 += s1; - s1 += buf[index++]; s2 += s1; - s1 += buf[index++]; s2 += s1; - s1 += buf[index++]; s2 += s1; - s1 += buf[index++]; s2 += s1; - s1 += buf[index++]; s2 += s1; - s1 += buf[index++]; s2 += s1; - s1 += buf[index++]; s2 += s1; - s1 += buf[index++]; s2 += s1; - s1 += buf[index++]; s2 += s1; - s1 += buf[index++]; s2 += s1; - k -= 16; - } - if (k != 0) - { - do - { - s1 += buf[index++]; - s2 += s1; - } - while (--k != 0); - } - s1 %= BASE; - s2 %= BASE; - } - return (uint)((s2 << 16) | s1); - } -#pragma warning restore 3001 -#pragma warning restore 3002 - - } - -} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/Compression/ZlibBaseStream.cs b/MinecraftClient/Protocol/Handlers/Compression/ZlibBaseStream.cs deleted file mode 100644 index a02c46a8..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/ZlibBaseStream.cs +++ /dev/null @@ -1,627 +0,0 @@ -// ZlibBaseStream.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation. -// 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-August-06 21:22:38> -// -// ------------------------------------------------------------------ -// -// This module defines the ZlibBaseStream class, which is an intnernal -// base class for DeflateStream, ZlibStream and GZipStream. -// -// ------------------------------------------------------------------ - -using System; -using System.IO; -using System.Runtime.CompilerServices; - -namespace Ionic.Zlib -{ - - internal enum ZlibStreamFlavor { ZLIB = 1950, DEFLATE = 1951, GZIP = 1952 } - - internal class ZlibBaseStream : System.IO.Stream - { - protected internal ZlibCodec _z = null; // deferred init... new ZlibCodec(); - - protected internal StreamMode _streamMode = StreamMode.Undefined; - protected internal FlushType _flushMode; - protected internal ZlibStreamFlavor _flavor; - protected internal CompressionMode _compressionMode; - protected internal CompressionLevel _level; - protected internal bool _leaveOpen; - protected internal byte[] _workingBuffer; - protected internal int _bufferSize = ZlibConstants.WorkingBufferSizeDefault; - protected internal byte[] _buf1 = new byte[1]; - - protected internal System.IO.Stream _stream; - protected internal CompressionStrategy Strategy = CompressionStrategy.Default; - - // workitem 7159 - Ionic.Crc.CRC32 crc; - protected internal string _GzipFileName; - protected internal string _GzipComment; - protected internal DateTime _GzipMtime; - protected internal int _gzipHeaderByteCount; - - internal int Crc32 { get { if (crc == null) return 0; return crc.Crc32Result; } } - - public ZlibBaseStream(System.IO.Stream stream, - CompressionMode compressionMode, - CompressionLevel level, - ZlibStreamFlavor flavor, - bool leaveOpen) - : base() - { - this._flushMode = FlushType.None; - //this._workingBuffer = new byte[WORKING_BUFFER_SIZE_DEFAULT]; - this._stream = stream; - this._leaveOpen = leaveOpen; - this._compressionMode = compressionMode; - this._flavor = flavor; - this._level = level; - // workitem 7159 - if (flavor == ZlibStreamFlavor.GZIP) - { - this.crc = new Ionic.Crc.CRC32(); - } - } - - - protected internal bool _wantCompress - { - get - { - return (this._compressionMode == CompressionMode.Compress); - } - } - - private ZlibCodec z - { - get - { - if (_z == null) - { - bool wantRfc1950Header = (this._flavor == ZlibStreamFlavor.ZLIB); - _z = new ZlibCodec(); - if (this._compressionMode == CompressionMode.Decompress) - { - _z.InitializeInflate(wantRfc1950Header); - } - else - { - _z.Strategy = Strategy; - _z.InitializeDeflate(this._level, wantRfc1950Header); - } - } - return _z; - } - } - - - - private byte[] workingBuffer - { - get - { - if (_workingBuffer == null) - _workingBuffer = new byte[_bufferSize]; - return _workingBuffer; - } - } - - - - public override void Write(System.Byte[] buffer, int offset, int count) - { - // workitem 7159 - // calculate the CRC on the unccompressed data (before writing) - if (crc != null) - crc.SlurpBlock(buffer, offset, count); - - if (_streamMode == StreamMode.Undefined) - _streamMode = StreamMode.Writer; - else if (_streamMode != StreamMode.Writer) - throw new ZlibException("Cannot Write after Reading."); - - if (count == 0) - return; - - // first reference of z property will initialize the private var _z - z.InputBuffer = buffer; - _z.NextIn = offset; - _z.AvailableBytesIn = count; - bool done = false; - do - { - _z.OutputBuffer = workingBuffer; - _z.NextOut = 0; - _z.AvailableBytesOut = _workingBuffer.Length; - int rc = (_wantCompress) - ? _z.Deflate(_flushMode) - : _z.Inflate(_flushMode); - if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END) - throw new ZlibException((_wantCompress ? "de" : "in") + "flating: " + _z.Message); - - //if (_workingBuffer.Length - _z.AvailableBytesOut > 0) - _stream.Write(_workingBuffer, 0, _workingBuffer.Length - _z.AvailableBytesOut); - - done = _z.AvailableBytesIn == 0 && _z.AvailableBytesOut != 0; - - // If GZIP and de-compress, we're done when 8 bytes remain. - if (_flavor == ZlibStreamFlavor.GZIP && !_wantCompress) - done = (_z.AvailableBytesIn == 8 && _z.AvailableBytesOut != 0); - - } - while (!done); - } - - - - private void finish() - { - if (_z == null) return; - - if (_streamMode == StreamMode.Writer) - { - bool done = false; - do - { - _z.OutputBuffer = workingBuffer; - _z.NextOut = 0; - _z.AvailableBytesOut = _workingBuffer.Length; - int rc = (_wantCompress) - ? _z.Deflate(FlushType.Finish) - : _z.Inflate(FlushType.Finish); - - if (rc != ZlibConstants.Z_STREAM_END && rc != ZlibConstants.Z_OK) - { - string verb = (_wantCompress ? "de" : "in") + "flating"; - if (_z.Message == null) - throw new ZlibException(String.Format("{0}: (rc = {1})", verb, rc)); - else - throw new ZlibException(verb + ": " + _z.Message); - } - - if (_workingBuffer.Length - _z.AvailableBytesOut > 0) - { - _stream.Write(_workingBuffer, 0, _workingBuffer.Length - _z.AvailableBytesOut); - } - - done = _z.AvailableBytesIn == 0 && _z.AvailableBytesOut != 0; - // If GZIP and de-compress, we're done when 8 bytes remain. - if (_flavor == ZlibStreamFlavor.GZIP && !_wantCompress) - done = (_z.AvailableBytesIn == 8 && _z.AvailableBytesOut != 0); - - } - while (!done); - - Flush(); - - // workitem 7159 - if (_flavor == ZlibStreamFlavor.GZIP) - { - if (_wantCompress) - { - // Emit the GZIP trailer: CRC32 and size mod 2^32 - int c1 = crc.Crc32Result; - _stream.Write(BitConverter.GetBytes(c1), 0, 4); - int c2 = (Int32)(crc.TotalBytesRead & 0x00000000FFFFFFFF); - _stream.Write(BitConverter.GetBytes(c2), 0, 4); - } - else - { - throw new ZlibException("Writing with decompression is not supported."); - } - } - } - // workitem 7159 - else if (_streamMode == StreamMode.Reader) - { - if (_flavor == ZlibStreamFlavor.GZIP) - { - if (!_wantCompress) - { - // workitem 8501: handle edge case (decompress empty stream) - if (_z.TotalBytesOut == 0L) - return; - - // Read and potentially verify the GZIP trailer: - // CRC32 and size mod 2^32 - byte[] trailer = new byte[8]; - - // workitems 8679 & 12554 - if (_z.AvailableBytesIn < 8) - { - // Make sure we have read to the end of the stream - Array.Copy(_z.InputBuffer, _z.NextIn, trailer, 0, _z.AvailableBytesIn); - int bytesNeeded = 8 - _z.AvailableBytesIn; - int bytesRead = _stream.Read(trailer, - _z.AvailableBytesIn, - bytesNeeded); - if (bytesNeeded != bytesRead) - { - throw new ZlibException(String.Format("Missing or incomplete GZIP trailer. Expected 8 bytes, got {0}.", - _z.AvailableBytesIn + bytesRead)); - } - } - else - { - Array.Copy(_z.InputBuffer, _z.NextIn, trailer, 0, trailer.Length); - } - - Int32 crc32_expected = BitConverter.ToInt32(trailer, 0); - Int32 crc32_actual = crc.Crc32Result; - Int32 isize_expected = BitConverter.ToInt32(trailer, 4); - Int32 isize_actual = (Int32)(_z.TotalBytesOut & 0x00000000FFFFFFFF); - - if (crc32_actual != crc32_expected) - throw new ZlibException(String.Format("Bad CRC32 in GZIP trailer. (actual({0:X8})!=expected({1:X8}))", crc32_actual, crc32_expected)); - - if (isize_actual != isize_expected) - throw new ZlibException(String.Format("Bad size in GZIP trailer. (actual({0})!=expected({1}))", isize_actual, isize_expected)); - - } - else - { - throw new ZlibException("Reading with compression is not supported."); - } - } - } - } - - - private void end() - { - if (z == null) - return; - if (_wantCompress) - { - _z.EndDeflate(); - } - else - { - _z.EndInflate(); - } - _z = null; - } - - - public override void Close() - { - if (_stream == null) return; - try - { - finish(); - } - finally - { - end(); - if (!_leaveOpen) _stream.Close(); - _stream = null; - } - } - - public override void Flush() - { - _stream.Flush(); - } - - public override System.Int64 Seek(System.Int64 offset, System.IO.SeekOrigin origin) - { - throw new NotImplementedException(); - //_outStream.Seek(offset, origin); - } - public override void SetLength(System.Int64 value) - { - _stream.SetLength(value); - } - - -#if NOT - public int Read() - { - if (Read(_buf1, 0, 1) == 0) - return 0; - // calculate CRC after reading - if (crc!=null) - crc.SlurpBlock(_buf1,0,1); - return (_buf1[0] & 0xFF); - } -#endif - - private bool nomoreinput = false; - - - - private string ReadZeroTerminatedString() - { - var list = new System.Collections.Generic.List(); - bool done = false; - do - { - // workitem 7740 - int n = _stream.Read(_buf1, 0, 1); - if (n != 1) - throw new ZlibException("Unexpected EOF reading GZIP header."); - else - { - if (_buf1[0] == 0) - done = true; - else - list.Add(_buf1[0]); - } - } while (!done); - byte[] a = list.ToArray(); - return GZipStream.iso8859dash1.GetString(a, 0, a.Length); - } - - - private int _ReadAndValidateGzipHeader() - { - int totalBytesRead = 0; - // read the header on the first read - byte[] header = new byte[10]; - int n = _stream.Read(header, 0, header.Length); - - // workitem 8501: handle edge case (decompress empty stream) - if (n == 0) - return 0; - - if (n != 10) - throw new ZlibException("Not a valid GZIP stream."); - - if (header[0] != 0x1F || header[1] != 0x8B || header[2] != 8) - throw new ZlibException("Bad GZIP header."); - - Int32 timet = BitConverter.ToInt32(header, 4); - _GzipMtime = GZipStream._unixEpoch.AddSeconds(timet); - totalBytesRead += n; - if ((header[3] & 0x04) == 0x04) - { - // read and discard extra field - n = _stream.Read(header, 0, 2); // 2-byte length field - totalBytesRead += n; - - Int16 extraLength = (Int16)(header[0] + header[1] * 256); - byte[] extra = new byte[extraLength]; - n = _stream.Read(extra, 0, extra.Length); - if (n != extraLength) - throw new ZlibException("Unexpected end-of-file reading GZIP header."); - totalBytesRead += n; - } - if ((header[3] & 0x08) == 0x08) - _GzipFileName = ReadZeroTerminatedString(); - if ((header[3] & 0x10) == 0x010) - _GzipComment = ReadZeroTerminatedString(); - if ((header[3] & 0x02) == 0x02) - Read(_buf1, 0, 1); // CRC16, ignore - - return totalBytesRead; - } - - - public override System.Int32 Read(System.Byte[] buffer, System.Int32 offset, System.Int32 count) - { - // According to MS documentation, any implementation of the IO.Stream.Read function must: - // (a) throw an exception if offset & count reference an invalid part of the buffer, - // or if count < 0, or if buffer is null - // (b) return 0 only upon EOF, or if count = 0 - // (c) if not EOF, then return at least 1 byte, up to bytes - - if (_streamMode == StreamMode.Undefined) - { - if (!this._stream.CanRead) throw new ZlibException("The stream is not readable."); - // for the first read, set up some controls. - _streamMode = StreamMode.Reader; - // (The first reference to _z goes through the private accessor which - // may initialize it.) - z.AvailableBytesIn = 0; - if (_flavor == ZlibStreamFlavor.GZIP) - { - _gzipHeaderByteCount = _ReadAndValidateGzipHeader(); - // workitem 8501: handle edge case (decompress empty stream) - if (_gzipHeaderByteCount == 0) - return 0; - } - } - - if (_streamMode != StreamMode.Reader) - throw new ZlibException("Cannot Read after Writing."); - - if (count == 0) return 0; - if (nomoreinput && _wantCompress) return 0; // workitem 8557 - if (buffer == null) throw new ArgumentNullException("buffer"); - if (count < 0) throw new ArgumentOutOfRangeException("count"); - if (offset < buffer.GetLowerBound(0)) throw new ArgumentOutOfRangeException("offset"); - if ((offset + count) > buffer.GetLength(0)) throw new ArgumentOutOfRangeException("count"); - - int rc = 0; - - // set up the output of the deflate/inflate codec: - _z.OutputBuffer = buffer; - _z.NextOut = offset; - _z.AvailableBytesOut = count; - - // This is necessary in case _workingBuffer has been resized. (new byte[]) - // (The first reference to _workingBuffer goes through the private accessor which - // may initialize it.) - _z.InputBuffer = workingBuffer; - - do - { - // need data in _workingBuffer in order to deflate/inflate. Here, we check if we have any. - if ((_z.AvailableBytesIn == 0) && (!nomoreinput)) - { - // No data available, so try to Read data from the captive stream. - _z.NextIn = 0; - _z.AvailableBytesIn = _stream.Read(_workingBuffer, 0, _workingBuffer.Length); - if (_z.AvailableBytesIn == 0) - nomoreinput = true; - - } - // we have data in InputBuffer; now compress or decompress as appropriate - rc = (_wantCompress) - ? _z.Deflate(_flushMode) - : _z.Inflate(_flushMode); - - if (nomoreinput && (rc == ZlibConstants.Z_BUF_ERROR)) - return 0; - - if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END) - throw new ZlibException(String.Format("{0}flating: rc={1} msg={2}", (_wantCompress ? "de" : "in"), rc, _z.Message)); - - if ((nomoreinput || rc == ZlibConstants.Z_STREAM_END) && (_z.AvailableBytesOut == count)) - break; // nothing more to read - } - //while (_z.AvailableBytesOut == count && rc == ZlibConstants.Z_OK); - while (_z.AvailableBytesOut > 0 && !nomoreinput && rc == ZlibConstants.Z_OK); - - - // workitem 8557 - // is there more room in output? - if (_z.AvailableBytesOut > 0) - { - if (rc == ZlibConstants.Z_OK && _z.AvailableBytesIn == 0) - { - // deferred - } - - // are we completely done reading? - if (nomoreinput) - { - // and in compression? - if (_wantCompress) - { - // no more input data available; therefore we flush to - // try to complete the read - rc = _z.Deflate(FlushType.Finish); - - if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END) - throw new ZlibException(String.Format("Deflating: rc={0} msg={1}", rc, _z.Message)); - } - } - } - - - rc = (count - _z.AvailableBytesOut); - - // calculate CRC after reading - if (crc != null) - crc.SlurpBlock(buffer, offset, rc); - - return rc; - } - - - - public override System.Boolean CanRead - { - get { return this._stream.CanRead; } - } - - public override System.Boolean CanSeek - { - get { return this._stream.CanSeek; } - } - - public override System.Boolean CanWrite - { - get { return this._stream.CanWrite; } - } - - public override System.Int64 Length - { - get { return _stream.Length; } - } - - public override long Position - { - get { throw new NotImplementedException(); } - set { throw new NotImplementedException(); } - } - - internal enum StreamMode - { - Writer, - Reader, - Undefined, - } - - - public static void CompressString(String s, Stream compressor) - { - byte[] uncompressed = System.Text.Encoding.UTF8.GetBytes(s); - using (compressor) - { - compressor.Write(uncompressed, 0, uncompressed.Length); - } - } - - public static void CompressBuffer(byte[] b, Stream compressor) - { - // workitem 8460 - using (compressor) - { - compressor.Write(b, 0, b.Length); - } - } - - public static String UncompressString(byte[] compressed, Stream decompressor) - { - // workitem 8460 - byte[] working = new byte[1024]; - var encoding = System.Text.Encoding.UTF8; - using (var output = new MemoryStream()) - { - using (decompressor) - { - int n; - while ((n = decompressor.Read(working, 0, working.Length)) != 0) - { - output.Write(working, 0, n); - } - } - - // reset to allow read from start - output.Seek(0, SeekOrigin.Begin); - var sr = new StreamReader(output, encoding); - return sr.ReadToEnd(); - } - } - - public static byte[] UncompressBuffer(byte[] compressed, Stream decompressor) - { - // workitem 8460 - byte[] working = new byte[1024]; - using (var output = new MemoryStream()) - { - using (decompressor) - { - int n; - while ((n = decompressor.Read(working, 0, working.Length)) != 0) - { - output.Write(working, 0, n); - } - } - return output.ToArray(); - } - } - - } - - -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/ZlibCodec.cs b/MinecraftClient/Protocol/Handlers/Compression/ZlibCodec.cs deleted file mode 100644 index e6b7299e..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/ZlibCodec.cs +++ /dev/null @@ -1,718 +0,0 @@ -// ZlibCodec.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation. -// 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: <2009-November-03 15:40:51> -// -// ------------------------------------------------------------------ -// -// This module defines a Codec for ZLIB compression and -// decompression. This code extends code that was based the jzlib -// implementation of zlib, but this code is completely novel. The codec -// class is new, and encapsulates some behaviors that are new, and some -// that were present in other classes in the jzlib code base. In -// keeping with the license for jzlib, the copyright to the jzlib code -// is included below. -// -// ------------------------------------------------------------------ -// -// Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in -// the documentation and/or other materials provided with the distribution. -// -// 3. The names of the authors may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -// INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// ----------------------------------------------------------------------- -// -// This program is based on zlib-1.1.3; credit to authors -// Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) -// and contributors of zlib. -// -// ----------------------------------------------------------------------- - - -using System; -using System.Runtime.CompilerServices; -using Interop=System.Runtime.InteropServices; - -namespace Ionic.Zlib -{ - /// - /// Encoder and Decoder for ZLIB and DEFLATE (IETF RFC1950 and RFC1951). - /// - /// - /// - /// This class compresses and decompresses data according to the Deflate algorithm - /// and optionally, the ZLIB format, as documented in RFC 1950 - ZLIB and RFC 1951 - DEFLATE. - /// - [Interop.GuidAttribute("ebc25cf6-9120-4283-b972-0e5520d0000D")] - [Interop.ComVisible(true)] -#if !NETCF - [Interop.ClassInterface(Interop.ClassInterfaceType.AutoDispatch)] -#endif - sealed public class ZlibCodec - { - /// - /// The buffer from which data is taken. - /// - public byte[] InputBuffer; - - /// - /// An index into the InputBuffer array, indicating where to start reading. - /// - public int NextIn; - - /// - /// The number of bytes available in the InputBuffer, starting at NextIn. - /// - /// - /// Generally you should set this to InputBuffer.Length before the first Inflate() or Deflate() call. - /// The class will update this number as calls to Inflate/Deflate are made. - /// - public int AvailableBytesIn; - - /// - /// Total number of bytes read so far, through all calls to Inflate()/Deflate(). - /// - public long TotalBytesIn; - - /// - /// Buffer to store output data. - /// - public byte[] OutputBuffer; - - /// - /// An index into the OutputBuffer array, indicating where to start writing. - /// - public int NextOut; - - /// - /// The number of bytes available in the OutputBuffer, starting at NextOut. - /// - /// - /// Generally you should set this to OutputBuffer.Length before the first Inflate() or Deflate() call. - /// The class will update this number as calls to Inflate/Deflate are made. - /// - public int AvailableBytesOut; - - /// - /// Total number of bytes written to the output so far, through all calls to Inflate()/Deflate(). - /// - public long TotalBytesOut; - - /// - /// used for diagnostics, when something goes wrong! - /// - public System.String Message; - - internal DeflateManager dstate; - internal InflateManager istate; - - internal uint _Adler32; - - /// - /// The compression level to use in this codec. Useful only in compression mode. - /// - public CompressionLevel CompressLevel = CompressionLevel.Default; - - /// - /// The number of Window Bits to use. - /// - /// - /// This gauges the size of the sliding window, and hence the - /// compression effectiveness as well as memory consumption. It's best to just leave this - /// setting alone if you don't know what it is. The maximum value is 15 bits, which implies - /// a 32k window. - /// - public int WindowBits = ZlibConstants.WindowBitsDefault; - - /// - /// The compression strategy to use. - /// - /// - /// This is only effective in compression. The theory offered by ZLIB is that different - /// strategies could potentially produce significant differences in compression behavior - /// for different data sets. Unfortunately I don't have any good recommendations for how - /// to set it differently. When I tested changing the strategy I got minimally different - /// compression performance. It's best to leave this property alone if you don't have a - /// good feel for it. Or, you may want to produce a test harness that runs through the - /// different strategy options and evaluates them on different file types. If you do that, - /// let me know your results. - /// - public CompressionStrategy Strategy = CompressionStrategy.Default; - - - /// - /// The Adler32 checksum on the data transferred through the codec so far. You probably don't need to look at this. - /// - public int Adler32 { get { return (int)_Adler32; } } - - - /// - /// Create a ZlibCodec. - /// - /// - /// If you use this default constructor, you will later have to explicitly call - /// InitializeInflate() or InitializeDeflate() before using the ZlibCodec to compress - /// or decompress. - /// - public ZlibCodec() { } - - /// - /// Create a ZlibCodec that either compresses or decompresses. - /// - /// - /// Indicates whether the codec should compress (deflate) or decompress (inflate). - /// - public ZlibCodec(CompressionMode mode) - { - if (mode == CompressionMode.Compress) - { - int rc = InitializeDeflate(); - if (rc != ZlibConstants.Z_OK) throw new ZlibException("Cannot initialize for deflate."); - } - else if (mode == CompressionMode.Decompress) - { - int rc = InitializeInflate(); - if (rc != ZlibConstants.Z_OK) throw new ZlibException("Cannot initialize for inflate."); - } - else throw new ZlibException("Invalid ZlibStreamFlavor."); - } - - /// - /// Initialize the inflation state. - /// - /// - /// It is not necessary to call this before using the ZlibCodec to inflate data; - /// It is implicitly called when you call the constructor. - /// - /// Z_OK if everything goes well. - public int InitializeInflate() - { - return InitializeInflate(this.WindowBits); - } - - /// - /// Initialize the inflation state with an explicit flag to - /// govern the handling of RFC1950 header bytes. - /// - /// - /// - /// By default, the ZLIB header defined in RFC 1950 is expected. If - /// you want to read a zlib stream you should specify true for - /// expectRfc1950Header. If you have a deflate stream, you will want to specify - /// false. It is only necessary to invoke this initializer explicitly if you - /// want to specify false. - /// - /// - /// whether to expect an RFC1950 header byte - /// pair when reading the stream of data to be inflated. - /// - /// Z_OK if everything goes well. - public int InitializeInflate(bool expectRfc1950Header) - { - return InitializeInflate(this.WindowBits, expectRfc1950Header); - } - - /// - /// Initialize the ZlibCodec for inflation, with the specified number of window bits. - /// - /// The number of window bits to use. If you need to ask what that is, - /// then you shouldn't be calling this initializer. - /// Z_OK if all goes well. - public int InitializeInflate(int windowBits) - { - this.WindowBits = windowBits; - return InitializeInflate(windowBits, true); - } - - /// - /// Initialize the inflation state with an explicit flag to govern the handling of - /// RFC1950 header bytes. - /// - /// - /// - /// If you want to read a zlib stream you should specify true for - /// expectRfc1950Header. In this case, the library will expect to find a ZLIB - /// header, as defined in RFC - /// 1950, in the compressed stream. If you will be reading a DEFLATE or - /// GZIP stream, which does not have such a header, you will want to specify - /// false. - /// - /// - /// whether to expect an RFC1950 header byte pair when reading - /// the stream of data to be inflated. - /// The number of window bits to use. If you need to ask what that is, - /// then you shouldn't be calling this initializer. - /// Z_OK if everything goes well. - public int InitializeInflate(int windowBits, bool expectRfc1950Header) - { - this.WindowBits = windowBits; - if (dstate != null) throw new ZlibException("You may not call InitializeInflate() after calling InitializeDeflate()."); - istate = new InflateManager(expectRfc1950Header); - return istate.Initialize(this, windowBits); - } - - /// - /// Inflate the data in the InputBuffer, placing the result in the OutputBuffer. - /// - /// - /// You must have set InputBuffer and OutputBuffer, NextIn and NextOut, and AvailableBytesIn and - /// AvailableBytesOut before calling this method. - /// - /// - /// - /// private void InflateBuffer() - /// { - /// int bufferSize = 1024; - /// byte[] buffer = new byte[bufferSize]; - /// ZlibCodec decompressor = new ZlibCodec(); - /// - /// Console.WriteLine("\n============================================"); - /// Console.WriteLine("Size of Buffer to Inflate: {0} bytes.", CompressedBytes.Length); - /// MemoryStream ms = new MemoryStream(DecompressedBytes); - /// - /// int rc = decompressor.InitializeInflate(); - /// - /// decompressor.InputBuffer = CompressedBytes; - /// decompressor.NextIn = 0; - /// decompressor.AvailableBytesIn = CompressedBytes.Length; - /// - /// decompressor.OutputBuffer = buffer; - /// - /// // pass 1: inflate - /// do - /// { - /// decompressor.NextOut = 0; - /// decompressor.AvailableBytesOut = buffer.Length; - /// rc = decompressor.Inflate(FlushType.None); - /// - /// if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END) - /// throw new Exception("inflating: " + decompressor.Message); - /// - /// ms.Write(decompressor.OutputBuffer, 0, buffer.Length - decompressor.AvailableBytesOut); - /// } - /// while (decompressor.AvailableBytesIn > 0 || decompressor.AvailableBytesOut == 0); - /// - /// // pass 2: finish and flush - /// do - /// { - /// decompressor.NextOut = 0; - /// decompressor.AvailableBytesOut = buffer.Length; - /// rc = decompressor.Inflate(FlushType.Finish); - /// - /// if (rc != ZlibConstants.Z_STREAM_END && rc != ZlibConstants.Z_OK) - /// throw new Exception("inflating: " + decompressor.Message); - /// - /// if (buffer.Length - decompressor.AvailableBytesOut > 0) - /// ms.Write(buffer, 0, buffer.Length - decompressor.AvailableBytesOut); - /// } - /// while (decompressor.AvailableBytesIn > 0 || decompressor.AvailableBytesOut == 0); - /// - /// decompressor.EndInflate(); - /// } - /// - /// - /// - /// The flush to use when inflating. - /// Z_OK if everything goes well. - public int Inflate(FlushType flush) - { - if (istate == null) - throw new ZlibException("No Inflate State!"); - return istate.Inflate(flush); - } - - - /// - /// Ends an inflation session. - /// - /// - /// Call this after successively calling Inflate(). This will cause all buffers to be flushed. - /// After calling this you cannot call Inflate() without a intervening call to one of the - /// InitializeInflate() overloads. - /// - /// Z_OK if everything goes well. - public int EndInflate() - { - if (istate == null) - throw new ZlibException("No Inflate State!"); - int ret = istate.End(); - istate = null; - return ret; - } - - /// - /// I don't know what this does! - /// - /// Z_OK if everything goes well. - public int SyncInflate() - { - if (istate == null) - throw new ZlibException("No Inflate State!"); - return istate.Sync(); - } - - /// - /// Initialize the ZlibCodec for deflation operation. - /// - /// - /// The codec will use the MAX window bits and the default level of compression. - /// - /// - /// - /// int bufferSize = 40000; - /// byte[] CompressedBytes = new byte[bufferSize]; - /// byte[] DecompressedBytes = new byte[bufferSize]; - /// - /// ZlibCodec compressor = new ZlibCodec(); - /// - /// compressor.InitializeDeflate(CompressionLevel.Default); - /// - /// compressor.InputBuffer = System.Text.ASCIIEncoding.ASCII.GetBytes(TextToCompress); - /// compressor.NextIn = 0; - /// compressor.AvailableBytesIn = compressor.InputBuffer.Length; - /// - /// compressor.OutputBuffer = CompressedBytes; - /// compressor.NextOut = 0; - /// compressor.AvailableBytesOut = CompressedBytes.Length; - /// - /// while (compressor.TotalBytesIn != TextToCompress.Length && compressor.TotalBytesOut < bufferSize) - /// { - /// compressor.Deflate(FlushType.None); - /// } - /// - /// while (true) - /// { - /// int rc= compressor.Deflate(FlushType.Finish); - /// if (rc == ZlibConstants.Z_STREAM_END) break; - /// } - /// - /// compressor.EndDeflate(); - /// - /// - /// - /// Z_OK if all goes well. You generally don't need to check the return code. - public int InitializeDeflate() - { - return _InternalInitializeDeflate(true); - } - - /// - /// Initialize the ZlibCodec for deflation operation, using the specified CompressionLevel. - /// - /// - /// The codec will use the maximum window bits (15) and the specified - /// CompressionLevel. It will emit a ZLIB stream as it compresses. - /// - /// The compression level for the codec. - /// Z_OK if all goes well. - public int InitializeDeflate(CompressionLevel level) - { - this.CompressLevel = level; - return _InternalInitializeDeflate(true); - } - - - /// - /// Initialize the ZlibCodec for deflation operation, using the specified CompressionLevel, - /// and the explicit flag governing whether to emit an RFC1950 header byte pair. - /// - /// - /// The codec will use the maximum window bits (15) and the specified CompressionLevel. - /// If you want to generate a zlib stream, you should specify true for - /// wantRfc1950Header. In this case, the library will emit a ZLIB - /// header, as defined in RFC - /// 1950, in the compressed stream. - /// - /// The compression level for the codec. - /// whether to emit an initial RFC1950 byte pair in the compressed stream. - /// Z_OK if all goes well. - public int InitializeDeflate(CompressionLevel level, bool wantRfc1950Header) - { - this.CompressLevel = level; - return _InternalInitializeDeflate(wantRfc1950Header); - } - - - /// - /// Initialize the ZlibCodec for deflation operation, using the specified CompressionLevel, - /// and the specified number of window bits. - /// - /// - /// The codec will use the specified number of window bits and the specified CompressionLevel. - /// - /// The compression level for the codec. - /// the number of window bits to use. If you don't know what this means, don't use this method. - /// Z_OK if all goes well. - public int InitializeDeflate(CompressionLevel level, int bits) - { - this.CompressLevel = level; - this.WindowBits = bits; - return _InternalInitializeDeflate(true); - } - - /// - /// Initialize the ZlibCodec for deflation operation, using the specified - /// CompressionLevel, the specified number of window bits, and the explicit flag - /// governing whether to emit an RFC1950 header byte pair. - /// - /// - /// The compression level for the codec. - /// whether to emit an initial RFC1950 byte pair in the compressed stream. - /// the number of window bits to use. If you don't know what this means, don't use this method. - /// Z_OK if all goes well. - public int InitializeDeflate(CompressionLevel level, int bits, bool wantRfc1950Header) - { - this.CompressLevel = level; - this.WindowBits = bits; - return _InternalInitializeDeflate(wantRfc1950Header); - } - - private int _InternalInitializeDeflate(bool wantRfc1950Header) - { - if (istate != null) throw new ZlibException("You may not call InitializeDeflate() after calling InitializeInflate()."); - dstate = new DeflateManager(); - dstate.WantRfc1950HeaderBytes = wantRfc1950Header; - - return dstate.Initialize(this, this.CompressLevel, this.WindowBits, this.Strategy); - } - - /// - /// Deflate one batch of data. - /// - /// - /// You must have set InputBuffer and OutputBuffer before calling this method. - /// - /// - /// - /// private void DeflateBuffer(CompressionLevel level) - /// { - /// int bufferSize = 1024; - /// byte[] buffer = new byte[bufferSize]; - /// ZlibCodec compressor = new ZlibCodec(); - /// - /// Console.WriteLine("\n============================================"); - /// Console.WriteLine("Size of Buffer to Deflate: {0} bytes.", UncompressedBytes.Length); - /// MemoryStream ms = new MemoryStream(); - /// - /// int rc = compressor.InitializeDeflate(level); - /// - /// compressor.InputBuffer = UncompressedBytes; - /// compressor.NextIn = 0; - /// compressor.AvailableBytesIn = UncompressedBytes.Length; - /// - /// compressor.OutputBuffer = buffer; - /// - /// // pass 1: deflate - /// do - /// { - /// compressor.NextOut = 0; - /// compressor.AvailableBytesOut = buffer.Length; - /// rc = compressor.Deflate(FlushType.None); - /// - /// if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END) - /// throw new Exception("deflating: " + compressor.Message); - /// - /// ms.Write(compressor.OutputBuffer, 0, buffer.Length - compressor.AvailableBytesOut); - /// } - /// while (compressor.AvailableBytesIn > 0 || compressor.AvailableBytesOut == 0); - /// - /// // pass 2: finish and flush - /// do - /// { - /// compressor.NextOut = 0; - /// compressor.AvailableBytesOut = buffer.Length; - /// rc = compressor.Deflate(FlushType.Finish); - /// - /// if (rc != ZlibConstants.Z_STREAM_END && rc != ZlibConstants.Z_OK) - /// throw new Exception("deflating: " + compressor.Message); - /// - /// if (buffer.Length - compressor.AvailableBytesOut > 0) - /// ms.Write(buffer, 0, buffer.Length - compressor.AvailableBytesOut); - /// } - /// while (compressor.AvailableBytesIn > 0 || compressor.AvailableBytesOut == 0); - /// - /// compressor.EndDeflate(); - /// - /// ms.Seek(0, SeekOrigin.Begin); - /// CompressedBytes = new byte[compressor.TotalBytesOut]; - /// ms.Read(CompressedBytes, 0, CompressedBytes.Length); - /// } - /// - /// - /// whether to flush all data as you deflate. Generally you will want to - /// use Z_NO_FLUSH here, in a series of calls to Deflate(), and then call EndDeflate() to - /// flush everything. - /// - /// Z_OK if all goes well. - public int Deflate(FlushType flush) - { - if (dstate == null) - throw new ZlibException("No Deflate State!"); - return dstate.Deflate(flush); - } - - /// - /// End a deflation session. - /// - /// - /// Call this after making a series of one or more calls to Deflate(). All buffers are flushed. - /// - /// Z_OK if all goes well. - public int EndDeflate() - { - if (dstate == null) - throw new ZlibException("No Deflate State!"); - //dinoch Tue, 03 Nov 2009 15:39 (test this) - //int ret = dstate.End(); - dstate = null; - return ZlibConstants.Z_OK; //ret; - } - - /// - /// Reset a codec for another deflation session. - /// - /// - /// Call this to reset the deflation state. For example if a thread is deflating - /// non-consecutive blocks, you can call Reset() after the Deflate(Sync) of the first - /// block and before the next Deflate(None) of the second block. - /// - /// Z_OK if all goes well. - public void ResetDeflate() - { - if (dstate == null) - throw new ZlibException("No Deflate State!"); - dstate.Reset(); - } - - - /// - /// Set the CompressionStrategy and CompressionLevel for a deflation session. - /// - /// the level of compression to use. - /// the strategy to use for compression. - /// Z_OK if all goes well. - public int SetDeflateParams(CompressionLevel level, CompressionStrategy strategy) - { - if (dstate == null) - throw new ZlibException("No Deflate State!"); - return dstate.SetParams(level, strategy); - } - - - /// - /// Set the dictionary to be used for either Inflation or Deflation. - /// - /// The dictionary bytes to use. - /// Z_OK if all goes well. - public int SetDictionary(byte[] dictionary) - { - if (istate != null) - return istate.SetDictionary(dictionary); - - if (dstate != null) - return dstate.SetDictionary(dictionary); - - throw new ZlibException("No Inflate or Deflate state!"); - } - - // Flush as much pending output as possible. All deflate() output goes - // through this function so some applications may wish to modify it - // to avoid allocating a large strm->next_out buffer and copying into it. - // (See also read_buf()). - internal void flush_pending() - { - int len = dstate.pendingCount; - - if (len > AvailableBytesOut) - len = AvailableBytesOut; - if (len == 0) - return; - - if (dstate.pending.Length <= dstate.nextPending || - OutputBuffer.Length <= NextOut || - dstate.pending.Length < (dstate.nextPending + len) || - OutputBuffer.Length < (NextOut + len)) - { - throw new ZlibException(String.Format("Invalid State. (pending.Length={0}, pendingCount={1})", - dstate.pending.Length, dstate.pendingCount)); - } - - Array.Copy(dstate.pending, dstate.nextPending, OutputBuffer, NextOut, len); - - NextOut += len; - dstate.nextPending += len; - TotalBytesOut += len; - AvailableBytesOut -= len; - dstate.pendingCount -= len; - if (dstate.pendingCount == 0) - { - dstate.nextPending = 0; - } - } - - // Read a new buffer from the current input stream, update the adler32 - // and total number of bytes read. All deflate() input goes through - // this function so some applications may wish to modify it to avoid - // allocating a large strm->next_in buffer and copying from it. - // (See also flush_pending()). - internal int read_buf(byte[] buf, int start, int size) - { - int len = AvailableBytesIn; - - if (len > size) - len = size; - if (len == 0) - return 0; - - AvailableBytesIn -= len; - - if (dstate.WantRfc1950HeaderBytes) - { - _Adler32 = Adler.Adler32(_Adler32, InputBuffer, NextIn, len); - } - Array.Copy(InputBuffer, NextIn, buf, start, len); - NextIn += len; - TotalBytesIn += len; - return len; - } - - } -} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/Compression/ZlibConstants.cs b/MinecraftClient/Protocol/Handlers/Compression/ZlibConstants.cs deleted file mode 100644 index 6a473afc..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/ZlibConstants.cs +++ /dev/null @@ -1,127 +0,0 @@ -// ZlibConstants.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation. -// 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: <2009-November-03 18:50:19> -// -// ------------------------------------------------------------------ -// -// This module defines constants used by the zlib class library. This -// code is derived from the jzlib implementation of zlib, but -// significantly modified. In keeping with the license for jzlib, the -// copyright to that code is included here. -// -// ------------------------------------------------------------------ -// -// Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in -// the documentation and/or other materials provided with the distribution. -// -// 3. The names of the authors may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, -// INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, -// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// ----------------------------------------------------------------------- -// -// This program is based on zlib-1.1.3; credit to authors -// Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) -// and contributors of zlib. -// -// ----------------------------------------------------------------------- - - -using System; - -namespace Ionic.Zlib -{ - /// - /// A bunch of constants used in the Zlib interface. - /// - public static class ZlibConstants - { - /// - /// The maximum number of window bits for the Deflate algorithm. - /// - public const int WindowBitsMax = 15; // 32K LZ77 window - - /// - /// The default number of window bits for the Deflate algorithm. - /// - public const int WindowBitsDefault = WindowBitsMax; - - /// - /// indicates everything is A-OK - /// - public const int Z_OK = 0; - - /// - /// Indicates that the last operation reached the end of the stream. - /// - public const int Z_STREAM_END = 1; - - /// - /// The operation ended in need of a dictionary. - /// - public const int Z_NEED_DICT = 2; - - /// - /// There was an error with the stream - not enough data, not open and readable, etc. - /// - public const int Z_STREAM_ERROR = -2; - - /// - /// There was an error with the data - not enough data, bad data, etc. - /// - public const int Z_DATA_ERROR = -3; - - /// - /// There was an error with the working buffer. - /// - public const int Z_BUF_ERROR = -5; - - /// - /// The size of the working buffer used in the ZlibCodec class. Defaults to 8192 bytes. - /// -#if NETCF - public const int WorkingBufferSizeDefault = 8192; -#else - public const int WorkingBufferSizeDefault = 16384; -#endif - /// - /// The minimum size of the working buffer used in the ZlibCodec class. Currently it is 128 bytes. - /// - public const int WorkingBufferSizeMin = 1024; - } - -} diff --git a/MinecraftClient/Protocol/Handlers/Compression/ZlibStream.cs b/MinecraftClient/Protocol/Handlers/Compression/ZlibStream.cs deleted file mode 100644 index fb1a85d9..00000000 --- a/MinecraftClient/Protocol/Handlers/Compression/ZlibStream.cs +++ /dev/null @@ -1,726 +0,0 @@ -// ZlibStream.cs -// ------------------------------------------------------------------ -// -// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation. -// 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:53:33> -// -// ------------------------------------------------------------------ -// -// This module defines the ZlibStream class, which is similar in idea to -// the System.IO.Compression.DeflateStream and -// System.IO.Compression.GZipStream classes in the .NET BCL. -// -// ------------------------------------------------------------------ - -using System; -using System.IO; -using System.Runtime.CompilerServices; - -namespace Ionic.Zlib -{ - - /// - /// Represents a Zlib stream for compression or decompression. - /// - /// - /// - /// - /// The ZlibStream is a Decorator on a . It adds ZLIB compression or decompression to any - /// stream. - /// - /// - /// Using this stream, applications can compress or decompress data via - /// stream Read() and Write() operations. Either compresssion or - /// decompression can occur through either reading or writing. The compression - /// format used is ZLIB, which is documented in IETF RFC 1950, "ZLIB Compressed - /// Data Format Specification version 3.3". This implementation of ZLIB always uses - /// DEFLATE as the compression method. (see IETF RFC 1951, "DEFLATE - /// Compressed Data Format Specification version 1.3.") - /// - /// - /// The ZLIB format allows for varying compression methods, window sizes, and dictionaries. - /// This implementation always uses the DEFLATE compression method, a preset dictionary, - /// and 15 window bits by default. - /// - /// - /// - /// This class is similar to , except that it adds the - /// RFC1950 header and trailer bytes to a compressed stream when compressing, or expects - /// the RFC1950 header and trailer bytes when decompressing. It is also similar to the - /// . - /// - /// - /// - /// - public class ZlibStream : System.IO.Stream - { - internal ZlibBaseStream _baseStream; - bool _disposed; - - /// - /// Create a ZlibStream using the specified CompressionMode. - /// - /// - /// - /// - /// When mode is CompressionMode.Compress, the ZlibStream - /// will use the default compression level. The "captive" stream will be - /// closed when the ZlibStream is closed. - /// - /// - /// - /// - /// - /// This example uses a ZlibStream to compress a file, and writes the - /// compressed data to another file. - /// - /// using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) - /// { - /// using (var raw = System.IO.File.Create(fileToCompress + ".zlib")) - /// { - /// using (Stream compressor = new ZlibStream(raw, CompressionMode.Compress)) - /// { - /// byte[] buffer = new byte[WORKING_BUFFER_SIZE]; - /// int n; - /// while ((n= input.Read(buffer, 0, buffer.Length)) != 0) - /// { - /// compressor.Write(buffer, 0, n); - /// } - /// } - /// } - /// } - /// - /// - /// Using input As Stream = File.OpenRead(fileToCompress) - /// Using raw As FileStream = File.Create(fileToCompress & ".zlib") - /// Using compressor As Stream = New ZlibStream(raw, CompressionMode.Compress) - /// Dim buffer As Byte() = New Byte(4096) {} - /// Dim n As Integer = -1 - /// Do While (n <> 0) - /// If (n > 0) Then - /// compressor.Write(buffer, 0, n) - /// End If - /// n = input.Read(buffer, 0, buffer.Length) - /// Loop - /// End Using - /// End Using - /// End Using - /// - /// - /// - /// The stream which will be read or written. - /// Indicates whether the ZlibStream will compress or decompress. - public ZlibStream(System.IO.Stream stream, CompressionMode mode) - : this(stream, mode, CompressionLevel.Default, false) - { - } - - /// - /// Create a ZlibStream using the specified CompressionMode and - /// the specified CompressionLevel. - /// - /// - /// - /// - /// - /// When mode is CompressionMode.Decompress, the level parameter is ignored. - /// The "captive" stream will be closed when the ZlibStream is closed. - /// - /// - /// - /// - /// - /// This example uses a ZlibStream to compress data from a file, and writes the - /// compressed data to another file. - /// - /// - /// using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) - /// { - /// using (var raw = System.IO.File.Create(fileToCompress + ".zlib")) - /// { - /// using (Stream compressor = new ZlibStream(raw, - /// CompressionMode.Compress, - /// CompressionLevel.BestCompression)) - /// { - /// byte[] buffer = new byte[WORKING_BUFFER_SIZE]; - /// int n; - /// while ((n= input.Read(buffer, 0, buffer.Length)) != 0) - /// { - /// compressor.Write(buffer, 0, n); - /// } - /// } - /// } - /// } - /// - /// - /// - /// Using input As Stream = File.OpenRead(fileToCompress) - /// Using raw As FileStream = File.Create(fileToCompress & ".zlib") - /// Using compressor As Stream = New ZlibStream(raw, CompressionMode.Compress, CompressionLevel.BestCompression) - /// Dim buffer As Byte() = New Byte(4096) {} - /// Dim n As Integer = -1 - /// Do While (n <> 0) - /// If (n > 0) Then - /// compressor.Write(buffer, 0, n) - /// End If - /// n = input.Read(buffer, 0, buffer.Length) - /// Loop - /// End Using - /// End Using - /// End Using - /// - /// - /// - /// The stream to be read or written while deflating or inflating. - /// Indicates whether the ZlibStream will compress or decompress. - /// A tuning knob to trade speed for effectiveness. - public ZlibStream(System.IO.Stream stream, CompressionMode mode, CompressionLevel level) - : this(stream, mode, level, false) - { - } - - /// - /// Create a ZlibStream using the specified CompressionMode, and - /// explicitly specify whether the captive stream should be left open after - /// Deflation or Inflation. - /// - /// - /// - /// - /// - /// When mode is CompressionMode.Compress, the ZlibStream will use - /// the default compression level. - /// - /// - /// - /// This constructor allows the application to request that the captive stream - /// remain open after the deflation or inflation occurs. By default, after - /// Close() is called on the stream, the captive stream is also - /// closed. In some cases this is not desired, for example if the stream is a - /// that will be re-read after - /// compression. Specify true for the parameter to leave the stream - /// open. - /// - /// - /// - /// See the other overloads of this constructor for example code. - /// - /// - /// - /// - /// The stream which will be read or written. This is called the - /// "captive" stream in other places in this documentation. - /// Indicates whether the ZlibStream will compress or decompress. - /// true if the application would like the stream to remain - /// open after inflation/deflation. - public ZlibStream(System.IO.Stream stream, CompressionMode mode, bool leaveOpen) - : this(stream, mode, CompressionLevel.Default, leaveOpen) - { - } - - /// - /// Create a ZlibStream using the specified CompressionMode - /// and the specified CompressionLevel, and explicitly specify - /// whether the stream should be left open after Deflation or Inflation. - /// - /// - /// - /// - /// - /// This constructor allows the application to request that the captive - /// stream remain open after the deflation or inflation occurs. By - /// default, after Close() is called on the stream, the captive - /// stream is also closed. In some cases this is not desired, for example - /// if the stream is a that will be - /// re-read after compression. Specify true for the parameter to leave the stream open. - /// - /// - /// - /// When mode is CompressionMode.Decompress, the level parameter is - /// ignored. - /// - /// - /// - /// - /// - /// - /// This example shows how to use a ZlibStream to compress the data from a file, - /// and store the result into another file. The filestream remains open to allow - /// additional data to be written to it. - /// - /// - /// using (var output = System.IO.File.Create(fileToCompress + ".zlib")) - /// { - /// using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) - /// { - /// using (Stream compressor = new ZlibStream(output, CompressionMode.Compress, CompressionLevel.BestCompression, true)) - /// { - /// byte[] buffer = new byte[WORKING_BUFFER_SIZE]; - /// int n; - /// while ((n= input.Read(buffer, 0, buffer.Length)) != 0) - /// { - /// compressor.Write(buffer, 0, n); - /// } - /// } - /// } - /// // can write additional data to the output stream here - /// } - /// - /// - /// Using output As FileStream = File.Create(fileToCompress & ".zlib") - /// Using input As Stream = File.OpenRead(fileToCompress) - /// Using compressor As Stream = New ZlibStream(output, CompressionMode.Compress, CompressionLevel.BestCompression, True) - /// Dim buffer As Byte() = New Byte(4096) {} - /// Dim n As Integer = -1 - /// Do While (n <> 0) - /// If (n > 0) Then - /// compressor.Write(buffer, 0, n) - /// End If - /// n = input.Read(buffer, 0, buffer.Length) - /// Loop - /// End Using - /// End Using - /// ' can write additional data to the output stream here. - /// End Using - /// - /// - /// - /// The stream which will be read or written. - /// - /// Indicates whether the ZlibStream will compress or decompress. - /// - /// - /// true if the application would like the stream to remain open after - /// inflation/deflation. - /// - /// - /// - /// A tuning knob to trade speed for effectiveness. This parameter is - /// effective only when mode is CompressionMode.Compress. - /// - public ZlibStream(System.IO.Stream stream, CompressionMode mode, CompressionLevel level, bool leaveOpen) - { - _baseStream = new ZlibBaseStream(stream, mode, level, ZlibStreamFlavor.ZLIB, leaveOpen); - } - - #region Zlib properties - - /// - /// This property sets the flush behavior on the stream. - /// Sorry, though, not sure exactly how to describe all the various settings. - /// - virtual public FlushType FlushMode - { - get { return (this._baseStream._flushMode); } - set - { - if (_disposed) throw new ObjectDisposedException("ZlibStream"); - this._baseStream._flushMode = value; - } - } - - /// - /// The size of the working buffer for the compression codec. - /// - /// - /// - /// - /// The working buffer is used for all stream operations. The default size is - /// 1024 bytes. The minimum size is 128 bytes. You may get better performance - /// with a larger buffer. Then again, you might not. You would have to test - /// it. - /// - /// - /// - /// Set this before the first call to Read() or Write() on the - /// stream. If you try to set it afterwards, it will throw. - /// - /// - public int BufferSize - { - get - { - return this._baseStream._bufferSize; - } - set - { - if (_disposed) throw new ObjectDisposedException("ZlibStream"); - if (this._baseStream._workingBuffer != null) - throw new ZlibException("The working buffer is already set."); - if (value < ZlibConstants.WorkingBufferSizeMin) - throw new ZlibException(String.Format("Don't be silly. {0} bytes?? Use a bigger buffer, at least {1}.", value, ZlibConstants.WorkingBufferSizeMin)); - this._baseStream._bufferSize = value; - } - } - - /// Returns the total number of bytes input so far. - virtual public long TotalIn - { - get { return this._baseStream._z.TotalBytesIn; } - } - - /// Returns the total number of bytes output so far. - virtual public long TotalOut - { - get { return this._baseStream._z.TotalBytesOut; } - } - - #endregion - - #region System.IO.Stream methods - - /// - /// Dispose the stream. - /// - /// - /// - /// This may or may not result in a Close() call on the captive - /// stream. See the constructors that have a leaveOpen parameter - /// for more information. - /// - /// - /// This method may be invoked in two distinct scenarios. If disposing - /// == true, the method has been called directly or indirectly by a - /// user's code, for example via the public Dispose() method. In this - /// case, both managed and unmanaged resources can be referenced and - /// disposed. If disposing == false, the method has been called by the - /// runtime from inside the object finalizer and this method should not - /// reference other objects; in that case only unmanaged resources must - /// be referenced or disposed. - /// - /// - /// - /// indicates whether the Dispose method was invoked by user code. - /// - protected override void Dispose(bool disposing) - { - try - { - if (!_disposed) - { - if (disposing && (this._baseStream != null)) - this._baseStream.Close(); - _disposed = true; - } - } - finally - { - base.Dispose(disposing); - } - } - - - /// - /// Indicates whether the stream can be read. - /// - /// - /// The return value depends on whether the captive stream supports reading. - /// - public override bool CanRead - { - get - { - if (_disposed) throw new ObjectDisposedException("ZlibStream"); - return _baseStream._stream.CanRead; - } - } - - /// - /// Indicates whether the stream supports Seek operations. - /// - /// - /// Always returns false. - /// - public override bool CanSeek - { - get { return false; } - } - - /// - /// Indicates whether the stream can be written. - /// - /// - /// The return value depends on whether the captive stream supports writing. - /// - public override bool CanWrite - { - get - { - if (_disposed) throw new ObjectDisposedException("ZlibStream"); - return _baseStream._stream.CanWrite; - } - } - - /// - /// Flush the stream. - /// - public override void Flush() - { - if (_disposed) throw new ObjectDisposedException("ZlibStream"); - _baseStream.Flush(); - } - - /// - /// Reading this property always throws a . - /// - public override long Length - { - get { throw new NotSupportedException(); } - } - - /// - /// The position of the stream pointer. - /// - /// - /// - /// Setting this property always throws a . Reading will return the total bytes - /// written out, if used in writing, or the total bytes read in, if used in - /// reading. The count may refer to compressed bytes or uncompressed bytes, - /// depending on how you've used the stream. - /// - public override long Position - { - get - { - if (this._baseStream._streamMode == Ionic.Zlib.ZlibBaseStream.StreamMode.Writer) - return this._baseStream._z.TotalBytesOut; - if (this._baseStream._streamMode == Ionic.Zlib.ZlibBaseStream.StreamMode.Reader) - return this._baseStream._z.TotalBytesIn; - return 0; - } - - set { throw new NotSupportedException(); } - } - - /// - /// Read data from the stream. - /// - /// - /// - /// - /// - /// If you wish to use the ZlibStream to compress data while reading, - /// you can create a ZlibStream with CompressionMode.Compress, - /// providing an uncompressed data stream. Then call Read() on that - /// ZlibStream, and the data read will be compressed. If you wish to - /// use the ZlibStream to decompress data while reading, you can create - /// a ZlibStream with CompressionMode.Decompress, providing a - /// readable compressed data stream. Then call Read() on that - /// ZlibStream, and the data will be decompressed as it is read. - /// - /// - /// - /// A ZlibStream can be used for Read() or Write(), but - /// not both. - /// - /// - /// - /// - /// - /// The buffer into which the read data should be placed. - /// - /// - /// the offset within that data array to put the first byte read. - /// - /// the number of bytes to read. - /// - /// the number of bytes read - public override int Read(byte[] buffer, int offset, int count) - { - if (_disposed) throw new ObjectDisposedException("ZlibStream"); - return _baseStream.Read(buffer, offset, count); - } - - /// - /// Calling this method always throws a . - /// - /// - /// The offset to seek to.... - /// IF THIS METHOD ACTUALLY DID ANYTHING. - /// - /// - /// The reference specifying how to apply the offset.... IF - /// THIS METHOD ACTUALLY DID ANYTHING. - /// - /// - /// nothing. This method always throws. - public override long Seek(long offset, System.IO.SeekOrigin origin) - { - throw new NotSupportedException(); - } - - /// - /// Calling this method always throws a . - /// - /// - /// The new value for the stream length.... IF - /// THIS METHOD ACTUALLY DID ANYTHING. - /// - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - /// - /// Write data to the stream. - /// - /// - /// - /// - /// - /// If you wish to use the ZlibStream to compress data while writing, - /// you can create a ZlibStream with CompressionMode.Compress, - /// and a writable output stream. Then call Write() on that - /// ZlibStream, providing uncompressed data as input. The data sent to - /// the output stream will be the compressed form of the data written. If you - /// wish to use the ZlibStream to decompress data while writing, you - /// can create a ZlibStream with CompressionMode.Decompress, and a - /// writable output stream. Then call Write() on that stream, - /// providing previously compressed data. The data sent to the output stream - /// will be the decompressed form of the data written. - /// - /// - /// - /// A ZlibStream can be used for Read() or Write(), but not both. - /// - /// - /// The buffer holding data to write to the stream. - /// the offset within that data array to find the first byte to write. - /// the number of bytes to write. - public override void Write(byte[] buffer, int offset, int count) - { - if (_disposed) throw new ObjectDisposedException("ZlibStream"); - _baseStream.Write(buffer, offset, count); - } - #endregion - - - /// - /// Compress a string into a byte array using ZLIB. - /// - /// - /// - /// Uncompress it with . - /// - /// - /// - /// - /// - /// - /// - /// A string to compress. The string will first be encoded - /// using UTF8, then compressed. - /// - /// - /// The string in compressed form - public static byte[] CompressString(String s) - { - using (var ms = new MemoryStream()) - { - Stream compressor = - new ZlibStream(ms, CompressionMode.Compress, CompressionLevel.BestCompression); - ZlibBaseStream.CompressString(s, compressor); - return ms.ToArray(); - } - } - - - /// - /// Compress a byte array into a new byte array using ZLIB. - /// - /// - /// - /// Uncompress it with . - /// - /// - /// - /// - /// - /// - /// A buffer to compress. - /// - /// - /// The data in compressed form - public static byte[] CompressBuffer(byte[] b) - { - using (var ms = new MemoryStream()) - { - Stream compressor = - new ZlibStream( ms, CompressionMode.Compress, CompressionLevel.BestCompression ); - - ZlibBaseStream.CompressBuffer(b, compressor); - return ms.ToArray(); - } - } - - - /// - /// Uncompress a ZLIB-compressed byte array into a single string. - /// - /// - /// - /// - /// - /// - /// A buffer containing ZLIB-compressed data. - /// - /// - /// The uncompressed string - public static String UncompressString(byte[] compressed) - { - using (var input = new MemoryStream(compressed)) - { - Stream decompressor = - new ZlibStream(input, CompressionMode.Decompress); - - return ZlibBaseStream.UncompressString(compressed, decompressor); - } - } - - - /// - /// Uncompress a ZLIB-compressed byte array into a byte array. - /// - /// - /// - /// - /// - /// - /// A buffer containing ZLIB-compressed data. - /// - /// - /// The data in uncompressed form - public static byte[] UncompressBuffer(byte[] compressed) - { - using (var input = new MemoryStream(compressed)) - { - Stream decompressor = - new ZlibStream( input, CompressionMode.Decompress ); - - return ZlibBaseStream.UncompressBuffer(compressed, decompressor); - } - } - - } - - -} \ No newline at end of file diff --git a/MinecraftClient/Protocol/Handlers/DataTypes.cs b/MinecraftClient/Protocol/Handlers/DataTypes.cs index 2e2e90b7..d64e75e5 100644 --- a/MinecraftClient/Protocol/Handlers/DataTypes.cs +++ b/MinecraftClient/Protocol/Handlers/DataTypes.cs @@ -1,14 +1,11 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Net.Sockets; -using MinecraftClient.Mapping; -using MinecraftClient.Crypto; -using MinecraftClient.Inventory; -using MinecraftClient.Mapping.EntityPalettes; -using MinecraftClient.Inventory.ItemPalettes; using System.Runtime.CompilerServices; +using System.Text; +using MinecraftClient.Inventory; +using MinecraftClient.Inventory.ItemPalettes; +using MinecraftClient.Mapping; +using MinecraftClient.Mapping.EntityPalettes; namespace MinecraftClient.Protocol.Handlers { @@ -20,7 +17,7 @@ namespace MinecraftClient.Protocol.Handlers /// /// Protocol version for adjusting data types /// - private int protocolversion; + private readonly int protocolversion; /// /// Initialize a new DataTypes instance @@ -28,7 +25,7 @@ namespace MinecraftClient.Protocol.Handlers /// Protocol version public DataTypes(int protocol) { - this.protocolversion = protocol; + protocolversion = protocol; } /// @@ -223,7 +220,7 @@ namespace MinecraftClient.Protocol.Handlers Span javaUUID = stackalloc byte[16]; for (int i = 0; i < 16; ++i) javaUUID[i] = cache.Dequeue(); - Guid guid = new Guid(javaUUID); + Guid guid = new(javaUUID); if (BitConverter.IsLittleEndian) guid = guid.ToLittleEndian(); return guid; @@ -402,9 +399,8 @@ namespace MinecraftClient.Protocol.Handlers /// Read a single item slot from a cache of bytes and remove it from the cache /// /// The item that was read or NULL for an empty slot - public Item ReadNextItemSlot(Queue cache, ItemPalette itemPalette) + public Item? ReadNextItemSlot(Queue cache, ItemPalette itemPalette) { - List slotData = new List(); if (protocolversion > Protocol18Handler.MC_1_13_Version) { // MC 1.13 and greater @@ -440,21 +436,15 @@ namespace MinecraftClient.Protocol.Handlers public Entity ReadNextEntity(Queue cache, EntityPalette entityPalette, bool living) { int entityID = ReadNextVarInt(cache); - Guid entityUUID = Guid.Empty; if (protocolversion > Protocol18Handler.MC_1_8_Version) - { - entityUUID = ReadNextUUID(cache); - } + ReadNextUUID(cache); + EntityType entityType; // Entity type data type change from byte to varint after 1.14 if (protocolversion > Protocol18Handler.MC_1_13_Version) - { entityType = entityPalette.FromId(ReadNextVarInt(cache), living); - } else - { entityType = entityPalette.FromId(ReadNextByte(cache), living); - } Double entityX = ReadNextDouble(cache); Double entityY = ReadNextDouble(cache); @@ -493,7 +483,7 @@ namespace MinecraftClient.Protocol.Handlers /// private Dictionary ReadNextNbt(Queue cache, bool root) { - Dictionary nbtData = new Dictionary(); + Dictionary nbtData = new(); if (root) { @@ -736,9 +726,9 @@ namespace MinecraftClient.Protocol.Handlers /// The item that was read or NULL for an empty slot public VillagerTrade ReadNextTrade(Queue cache, ItemPalette itemPalette) { - Item inputItem1 = ReadNextItemSlot(cache, itemPalette); - Item outputItem = ReadNextItemSlot(cache, itemPalette); - Item inputItem2 = null; + Item inputItem1 = ReadNextItemSlot(cache, itemPalette)!; + Item outputItem = ReadNextItemSlot(cache, itemPalette)!; + Item? inputItem2 = null; if (ReadNextBool(cache)) //check if villager has second item { inputItem2 = ReadNextItemSlot(cache, itemPalette); @@ -774,20 +764,19 @@ namespace MinecraftClient.Protocol.Handlers if (nbt == null || nbt.Count == 0) return new byte[] { 0 }; // TAG_End - List bytes = new List(); + List bytes = new(); if (root) { bytes.Add(10); // TAG_Compound // NBT root name - string rootName = null; + string? rootName = null; if (nbt.ContainsKey("")) rootName = nbt[""] as string; - if (rootName == null) - rootName = ""; + rootName ??= ""; bytes.AddRange(GetUShort((ushort)rootName.Length)); bytes.AddRange(Encoding.ASCII.GetBytes(rootName)); @@ -799,10 +788,9 @@ namespace MinecraftClient.Protocol.Handlers if (item.Key == "" && root) continue; - byte fieldType; byte[] fieldNameLength = GetUShort((ushort)item.Key.Length); byte[] fieldName = Encoding.ASCII.GetBytes(item.Key); - byte[] fieldData = GetNbtField(item.Value, out fieldType); + byte[] fieldData = GetNbtField(item.Value, out byte fieldType); bytes.Add(fieldType); bytes.AddRange(fieldNameLength); bytes.AddRange(fieldName); @@ -866,7 +854,7 @@ namespace MinecraftClient.Protocol.Handlers { fieldType = 9; // TAG_List - List list = new List((object[])obj); + List list = new((object[])obj); int arrayLengthTotal = list.Count; // Treat empty list as TAG_Byte, length 0 @@ -874,17 +862,15 @@ namespace MinecraftClient.Protocol.Handlers return ConcatBytes(new[] { (byte)1 }, GetInt(0)); // Encode first list item, retain its type - byte firstItemType; string firstItemTypeString = list[0].GetType().Name; - byte[] firstItemBytes = GetNbtField(list[0], out firstItemType); + byte[] firstItemBytes = GetNbtField(list[0], out byte firstItemType); list.RemoveAt(0); // Encode further list items, check they have the same type - byte subsequentItemType; - List subsequentItemsBytes = new List(); + List subsequentItemsBytes = new(); foreach (object item in list) { - subsequentItemsBytes.AddRange(GetNbtField(item, out subsequentItemType)); + subsequentItemsBytes.AddRange(GetNbtField(item, out byte subsequentItemType)); if (subsequentItemType != firstItemType) throw new System.IO.InvalidDataException( "GetNbt: Cannot encode object[] list with mixed types: " + firstItemTypeString + ", " + item.GetType().Name + " into NBT!"); @@ -903,7 +889,7 @@ namespace MinecraftClient.Protocol.Handlers fieldType = 11; // TAG_Int_Array int[] srcIntList = (int[])obj; - List encIntList = new List(); + List encIntList = new(); encIntList.AddRange(GetInt(srcIntList.Length)); foreach (int item in srcIntList) encIntList.AddRange(GetInt(item)); @@ -914,7 +900,7 @@ namespace MinecraftClient.Protocol.Handlers fieldType = 12; // TAG_Long_Array long[] srcLongList = (long[])obj; - List encLongList = new List(); + List encLongList = new(); encLongList.AddRange(GetInt(srcLongList.Length)); foreach (long item in srcLongList) encLongList.AddRange(GetLong(item)); @@ -933,7 +919,7 @@ namespace MinecraftClient.Protocol.Handlers /// Byte array for this integer public byte[] GetVarInt(int paramInt) { - List bytes = new List(); + List bytes = new(); while ((paramInt & -128) != 0) { bytes.Add((byte)(paramInt & 127 | 128)); @@ -950,8 +936,10 @@ namespace MinecraftClient.Protocol.Handlers /// Byte array for this boolean public byte[] GetBool(bool paramBool) { - List bytes = new List(); - bytes.Add((byte)Convert.ToByte(paramBool)); + List bytes = new() + { + (byte)Convert.ToByte(paramBool) + }; return bytes.ToArray(); } @@ -1138,16 +1126,16 @@ namespace MinecraftClient.Protocol.Handlers /// Block face byte enum public byte GetBlockFace(Direction direction) { - switch (direction) + return direction switch { - case Direction.Down: return 0; - case Direction.Up: return 1; - case Direction.North: return 2; - case Direction.South: return 3; - case Direction.West: return 4; - case Direction.East: return 5; - default: throw new NotImplementedException("Unknown direction: " + direction.ToString()); - } + Direction.Down => 0, + Direction.Up => 1, + Direction.North => 2, + Direction.South => 3, + Direction.West => 4, + Direction.East => 5, + _ => throw new NotImplementedException("Unknown direction: " + direction.ToString()), + }; } /// @@ -1167,7 +1155,7 @@ namespace MinecraftClient.Protocol.Handlers /// Array containing all the data public byte[] ConcatBytes(params byte[][] bytes) { - List result = new List(); + List result = new(); foreach (byte[] array in bytes) result.AddRange(array); return result.ToArray(); diff --git a/MinecraftClient/Protocol/Handlers/Forge/FMLHandshakeClientState.cs b/MinecraftClient/Protocol/Handlers/Forge/FMLHandshakeClientState.cs index a72b4ad5..4bc9bfb2 100755 --- a/MinecraftClient/Protocol/Handlers/Forge/FMLHandshakeClientState.cs +++ b/MinecraftClient/Protocol/Handlers/Forge/FMLHandshakeClientState.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MinecraftClient.Protocol.Handlers.Forge +namespace MinecraftClient.Protocol.Handlers.Forge { /// /// Copy of the forge enum for client states. diff --git a/MinecraftClient/Protocol/Handlers/Forge/FMLHandshakeDiscriminator.cs b/MinecraftClient/Protocol/Handlers/Forge/FMLHandshakeDiscriminator.cs index 2402eff0..6e9bca46 100755 --- a/MinecraftClient/Protocol/Handlers/Forge/FMLHandshakeDiscriminator.cs +++ b/MinecraftClient/Protocol/Handlers/Forge/FMLHandshakeDiscriminator.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MinecraftClient.Protocol.Handlers.Forge +namespace MinecraftClient.Protocol.Handlers.Forge { /// /// Different "discriminator byte" values for the forge handshake. diff --git a/MinecraftClient/Protocol/Handlers/Forge/FMLVersion.cs b/MinecraftClient/Protocol/Handlers/Forge/FMLVersion.cs index 8cf4de09..2590d473 100644 --- a/MinecraftClient/Protocol/Handlers/Forge/FMLVersion.cs +++ b/MinecraftClient/Protocol/Handlers/Forge/FMLVersion.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MinecraftClient.Protocol.Handlers.Forge +namespace MinecraftClient.Protocol.Handlers.Forge { /// /// Version of the FML protocol diff --git a/MinecraftClient/Protocol/Handlers/Forge/ForgeInfo.cs b/MinecraftClient/Protocol/Handlers/Forge/ForgeInfo.cs index 1d4e61cf..9e82a2ea 100755 --- a/MinecraftClient/Protocol/Handlers/Forge/ForgeInfo.cs +++ b/MinecraftClient/Protocol/Handlers/Forge/ForgeInfo.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient.Protocol.Handlers.Forge { @@ -42,9 +40,11 @@ namespace MinecraftClient.Protocol.Handlers.Forge switch (fmlVersion) { case FMLVersion.FML2: - this.Mods = new List(); - this.Mods.Add(new ForgeMod("forge", "ANY")); - this.Version = fmlVersion; + Mods = new List + { + new ForgeMod("forge", "ANY") + }; + Version = fmlVersion; break; default: throw new InvalidOperationException(Translations.Get("error.forgeforce")); @@ -58,8 +58,8 @@ namespace MinecraftClient.Protocol.Handlers.Forge /// Forge protocol version internal ForgeInfo(Json.JSONData data, FMLVersion fmlVersion) { - this.Mods = new List(); - this.Version = fmlVersion; + Mods = new List(); + Version = fmlVersion; switch (fmlVersion) { @@ -89,7 +89,7 @@ namespace MinecraftClient.Protocol.Handlers.Forge String modid = mod.Properties["modid"].StringValue; String modversion = mod.Properties["version"].StringValue; - this.Mods.Add(new ForgeMod(modid, modversion)); + Mods.Add(new ForgeMod(modid, modversion)); } break; @@ -129,7 +129,7 @@ namespace MinecraftClient.Protocol.Handlers.Forge String modid = mod.Properties["modId"].StringValue; String modmarker = mod.Properties["modmarker"].StringValue; - this.Mods.Add(new ForgeMod(modid, modmarker)); + Mods.Add(new ForgeMod(modid, modmarker)); } break; diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette110.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette110.cs index 8cf774ed..cff2b2ef 100644 --- a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette110.cs +++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette110.cs @@ -1,13 +1,10 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient.Protocol.Handlers.PacketPalettes { public class PacketPalette110 : PacketTypePalette { - private Dictionary typeIn = new Dictionary() + private readonly Dictionary typeIn = new() { { 0x00, PacketTypesIn.SpawnEntity }, { 0x01, PacketTypesIn.SpawnExperienceOrb }, @@ -87,7 +84,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes { 0x4B, PacketTypesIn.EntityEffect }, }; - private Dictionary typeOut = new Dictionary() + private readonly Dictionary typeOut = new() { { 0x00, PacketTypesOut.TeleportConfirm }, { 0x01, PacketTypesOut.TabComplete }, diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette112.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette112.cs index a2aae370..9ceb58b2 100644 --- a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette112.cs +++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette112.cs @@ -1,13 +1,10 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient.Protocol.Handlers.PacketPalettes { public class PacketPalette112 : PacketTypePalette { - private Dictionary typeIn = new Dictionary() + private readonly Dictionary typeIn = new() { { 0x00, PacketTypesIn.SpawnEntity }, { 0x01, PacketTypesIn.SpawnExperienceOrb }, @@ -90,7 +87,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes { 0x4E, PacketTypesIn.EntityEffect }, }; - private Dictionary typeOut = new Dictionary() + private readonly Dictionary typeOut = new() { { 0x00, PacketTypesOut.TeleportConfirm }, { 0x01, PacketTypesOut.Unknown }, diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette1122.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette1122.cs index 0b0052c4..6bfc613c 100644 --- a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette1122.cs +++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette1122.cs @@ -1,13 +1,10 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient.Protocol.Handlers.PacketPalettes { public class PacketPalette1122 : PacketTypePalette { - private Dictionary typeIn = new Dictionary() + private readonly Dictionary typeIn = new() { { 0x00, PacketTypesIn.SpawnEntity }, { 0x01, PacketTypesIn.SpawnExperienceOrb }, @@ -91,7 +88,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes { 0x4F, PacketTypesIn.EntityEffect }, }; - private Dictionary typeOut = new Dictionary() + private readonly Dictionary typeOut = new() { { 0x00, PacketTypesOut.TeleportConfirm }, { 0x01, PacketTypesOut.TabComplete }, diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette113.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette113.cs index 98da7bb2..7dbeac89 100644 --- a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette113.cs +++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette113.cs @@ -1,13 +1,10 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient.Protocol.Handlers.PacketPalettes { public class PacketPalette113 : PacketTypePalette { - private Dictionary typeIn = new Dictionary() + private readonly Dictionary typeIn = new() { { 0x00, PacketTypesIn.SpawnEntity }, { 0x01, PacketTypesIn.SpawnExperienceOrb }, @@ -97,7 +94,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes { 0x55, PacketTypesIn.Tags }, }; - private Dictionary typeOut = new Dictionary() + private readonly Dictionary typeOut = new() { { 0x00, PacketTypesOut.TeleportConfirm }, { 0x01, PacketTypesOut.QueryBlockNBT }, diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette114.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette114.cs index fb6a17c7..0ef512c2 100644 --- a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette114.cs +++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette114.cs @@ -1,13 +1,10 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient.Protocol.Handlers.PacketPalettes { public class PacketPalette114 : PacketTypePalette { - private Dictionary typeIn = new Dictionary() + private readonly Dictionary typeIn = new() { { 0x00, PacketTypesIn.SpawnEntity }, { 0x01, PacketTypesIn.SpawnExperienceOrb }, @@ -104,7 +101,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes { 0x5C, PacketTypesIn.AcknowledgePlayerDigging }, }; - private Dictionary typeOut = new Dictionary() + private readonly Dictionary typeOut = new() { { 0x00, PacketTypesOut.TeleportConfirm }, { 0x01, PacketTypesOut.QueryBlockNBT }, diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette115.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette115.cs index 51372120..445c4c82 100644 --- a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette115.cs +++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette115.cs @@ -1,13 +1,10 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient.Protocol.Handlers.PacketPalettes { public class PacketPalette115 : PacketTypePalette { - private Dictionary typeIn = new Dictionary() + private readonly Dictionary typeIn = new() { { 0x00, PacketTypesIn.SpawnEntity }, { 0x01, PacketTypesIn.SpawnExperienceOrb }, @@ -104,7 +101,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes { 0x5C, PacketTypesIn.Tags }, }; - private Dictionary typeOut = new Dictionary() + private readonly Dictionary typeOut = new() { { 0x00, PacketTypesOut.TeleportConfirm }, { 0x01, PacketTypesOut.QueryBlockNBT }, diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette116.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette116.cs index 11833d63..1e54c3aa 100644 --- a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette116.cs +++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette116.cs @@ -1,13 +1,10 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient.Protocol.Handlers.PacketPalettes { public class PacketPalette116 : PacketTypePalette { - private Dictionary typeIn = new Dictionary() + private readonly Dictionary typeIn = new() { { 0x00, PacketTypesIn.SpawnEntity }, { 0x01, PacketTypesIn.SpawnExperienceOrb }, @@ -103,7 +100,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes { 0x5B, PacketTypesIn.Tags }, }; - private Dictionary typeOut = new Dictionary() + private readonly Dictionary typeOut = new() { { 0x00, PacketTypesOut.TeleportConfirm }, { 0x01, PacketTypesOut.QueryBlockNBT }, diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette1162.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette1162.cs index 469997f7..260ad360 100644 --- a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette1162.cs +++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette1162.cs @@ -1,13 +1,10 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient.Protocol.Handlers.PacketPalettes { public class PacketPalette1162 : PacketTypePalette { - private Dictionary typeIn = new Dictionary() + private readonly Dictionary typeIn = new() { { 0x00, PacketTypesIn.SpawnEntity }, { 0x01, PacketTypesIn.SpawnExperienceOrb }, @@ -103,7 +100,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes { 0x5B, PacketTypesIn.Tags }, }; - private Dictionary typeOut = new Dictionary() + private readonly Dictionary typeOut = new() { { 0x00, PacketTypesOut.TeleportConfirm }, { 0x01, PacketTypesOut.QueryBlockNBT }, diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette117.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette117.cs index ed15c558..a28ec53a 100644 --- a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette117.cs +++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette117.cs @@ -4,7 +4,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes { public class PacketPalette117 : PacketTypePalette { - private Dictionary typeIn = new Dictionary() + private readonly Dictionary typeIn = new() { { 0x00, PacketTypesIn.SpawnEntity }, { 0x01, PacketTypesIn.SpawnExperienceOrb }, @@ -111,7 +111,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes { 0x66, PacketTypesIn.Tags }, }; - private Dictionary typeOut = new Dictionary() + private readonly Dictionary typeOut = new() { { 0x00, PacketTypesOut.TeleportConfirm }, { 0x01, PacketTypesOut.QueryBlockNBT }, diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette118.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette118.cs index 2a24b5fa..a1badb81 100644 --- a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette118.cs +++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette118.cs @@ -4,7 +4,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes { public class PacketPalette118 : PacketTypePalette { - private Dictionary typeIn = new Dictionary() + private readonly Dictionary typeIn = new() { { 0x00, PacketTypesIn.SpawnEntity }, { 0x01, PacketTypesIn.SpawnExperienceOrb }, @@ -112,7 +112,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes { 0x67, PacketTypesIn.Tags }, }; - private Dictionary typeOut = new Dictionary() + private readonly Dictionary typeOut = new() { { 0x00, PacketTypesOut.TeleportConfirm }, { 0x01, PacketTypesOut.QueryBlockNBT }, diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette119.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette119.cs index 139e8dd4..256a8692 100644 --- a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette119.cs +++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette119.cs @@ -4,7 +4,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes { public class PacketPalette119 : PacketTypePalette { - private Dictionary typeIn = new Dictionary() + private readonly Dictionary typeIn = new() { { 0x00, PacketTypesIn.SpawnEntity }, // Changed in 1.19 (Wiki name: Spawn Entity) - DONE { 0x01, PacketTypesIn.SpawnExperienceOrb }, // (Wiki name: Spawn Exeprience Orb) @@ -113,7 +113,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes { 0x68, PacketTypesIn.Tags }, // (Wiki name: Update Tags) }; - private Dictionary typeOut = new Dictionary() + private readonly Dictionary typeOut = new() { { 0x00, PacketTypesOut.TeleportConfirm }, // (Wiki name: Confirm Teleportation) { 0x01, PacketTypesOut.QueryBlockNBT }, // (Wiki name: Query Block Entity Tag) diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette1192.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette1192.cs index 053bb300..f497917e 100644 --- a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette1192.cs +++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette1192.cs @@ -4,7 +4,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes { public class PacketPalette1192 : PacketTypePalette { - private Dictionary typeIn = new Dictionary() + private readonly Dictionary typeIn = new() { { 0x00, PacketTypesIn.SpawnEntity }, // Changed in 1.19 (Wiki name: Spawn Entity) - DONE { 0x01, PacketTypesIn.SpawnExperienceOrb }, // (Wiki name: Spawn Exeprience Orb) @@ -116,7 +116,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes { 0x6B, PacketTypesIn.Tags }, // (Wiki name: Update Tags) }; - private Dictionary typeOut = new Dictionary() + private readonly Dictionary typeOut = new() { { 0x00, PacketTypesOut.TeleportConfirm }, // (Wiki name: Confirm Teleportation) { 0x01, PacketTypesOut.QueryBlockNBT }, // (Wiki name: Query Block Entity Tag) diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette17.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette17.cs index c87eb535..279e7fc6 100644 --- a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette17.cs +++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPalette17.cs @@ -1,13 +1,10 @@ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient.Protocol.Handlers.PacketPalettes { public class PacketPalette17 : PacketTypePalette { - private Dictionary typeIn = new Dictionary() + private readonly Dictionary typeIn = new() { { 0x00, PacketTypesIn.KeepAlive }, { 0x01, PacketTypesIn.JoinGame }, @@ -85,7 +82,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes { 0x49, PacketTypesIn.UpdateEntityNBT }, }; - private Dictionary typeOut = new Dictionary() + private readonly Dictionary typeOut = new() { { 0x00, PacketTypesOut.KeepAlive }, { 0x01, PacketTypesOut.ChatMessage }, diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPaletteHelper.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPaletteHelper.cs index fdaebcb7..84d53651 100644 --- a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPaletteHelper.cs +++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketPaletteHelper.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Collections.Generic; using System.IO; namespace MinecraftClient.Protocol.Handlers.PacketPalettes @@ -33,10 +30,12 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes public static void UpdatePacketIdByItemPosition(PacketTypePalette palette, string outputFile) { // I am just too tired to create another full .cs file so... please just copy and paste - List lines = new List(); - lines.Add("=== Inbound Packets ==="); + List lines = new() + { + "=== Inbound Packets ===" + }; int i = 0; - foreach(var t in palette.GetMappingIn()) + foreach (var t in palette.GetMappingIn()) { lines.Add(string.Format("{{ 0x{0}, {1} }},", i.ToString("X2"), t.Value)); i++; @@ -78,8 +77,10 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes public static void UpdatePacketPositionToAscending(PacketTypePalette palette, string outputFile) { // I am just too tired to create another full .cs file so... please just copy and paste - List lines = new List(); - lines.Add("=== Inbound Packets ==="); + List lines = new() + { + "=== Inbound Packets ===" + }; for (int i = 0; i < palette.GetMappingIn().Count; i++) { lines.Add(string.Format("{{ 0x{0}, {1} }},", i.ToString("X2"), palette.GetMappingIn()[i])); @@ -119,25 +120,24 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes const string TAB = " "; const string TAB2 = " "; const string TAB3 = " "; - List lines = new List(); - lines.Add("using System;"); - lines.Add("using System.Collections.Generic;"); - lines.Add("using System.Linq;"); - lines.Add("using System.Text;"); - lines.Add(""); - lines.Add("namespace " + namespaceToUse); - lines.Add("{"); - lines.Add(TAB + "public class " + className + " : PacketTypePalette"); - lines.Add(TAB + "{"); - lines.Add(TAB2 + "private Dictionary typeIn = new Dictionary()"); - lines.Add(TAB2 + "{"); + List lines = new() + { + "using System.Collections.Generic;", + "", + "namespace " + namespaceToUse, + "{", + TAB + "public class " + className + " : PacketTypePalette", + TAB + "{", + TAB2 + "private readonly Dictionary typeIn = new()", + TAB2 + "{" + }; for (int i = 0; i < pIn.Count; i++) { lines.Add(TAB3 + string.Format("{{ 0x{0}, PacketTypesIn.{1} }},", i.ToString("X2"), pIn[i])); } lines.Add(TAB2 + "};"); lines.Add(""); - lines.Add(TAB2 + "private Dictionary typeOut = new Dictionary()"); + lines.Add(TAB2 + "private readonly Dictionary typeOut = new()"); lines.Add(TAB2 + "{"); for (int i = 0; i < pOut.Count; i++) { diff --git a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketTypePalette.cs b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketTypePalette.cs index 3a3306d3..a65a0079 100644 --- a/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketTypePalette.cs +++ b/MinecraftClient/Protocol/Handlers/PacketPalettes/PacketTypePalette.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; +using System.Collections.Generic; namespace MinecraftClient.Protocol.Handlers.PacketPalettes { @@ -34,9 +30,9 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes protected abstract Dictionary GetListIn(); protected abstract Dictionary GetListOut(); - private Dictionary reverseMappingIn = new Dictionary(); + private readonly Dictionary reverseMappingIn = new(); - private Dictionary reverseMappingOut = new Dictionary(); + private readonly Dictionary reverseMappingOut = new(); private bool forgeEnabled = false; @@ -59,8 +55,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes /// Packet type public PacketTypesIn GetIncommingTypeById(int packetId) { - PacketTypesIn p; - if (GetListIn().TryGetValue(packetId, out p)) + if (GetListIn().TryGetValue(packetId, out PacketTypesIn p)) { return p; } @@ -91,8 +86,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes /// Packet type public PacketTypesOut GetOutgoingTypeById(int packetId) { - PacketTypesOut p; - if (GetListOut().TryGetValue(packetId, out p)) + if (GetListOut().TryGetValue(packetId, out PacketTypesOut p)) { return p; } @@ -130,7 +124,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes /// Public method for getting the type mapping /// /// PacketTypesOut with packet ID as index - public Dictionary GetMappingOut() + public Dictionary GetMappingOut() { return GetListOut(); } @@ -146,7 +140,7 @@ namespace MinecraftClient.Protocol.Handlers.PacketPalettes /// public void SetForgeEnabled(bool enabled) { - this.forgeEnabled = enabled; + forgeEnabled = enabled; } } } diff --git a/MinecraftClient/Protocol/Handlers/PacketType18Handler.cs b/MinecraftClient/Protocol/Handlers/PacketType18Handler.cs index 72a44990..b0ad5125 100644 --- a/MinecraftClient/Protocol/Handlers/PacketType18Handler.cs +++ b/MinecraftClient/Protocol/Handlers/PacketType18Handler.cs @@ -1,16 +1,12 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using MinecraftClient.Protocol.Handlers; using MinecraftClient.Protocol.Handlers.PacketPalettes; namespace MinecraftClient.Protocol.Handlers { public class PacketTypeHandler { - private int protocol; - private bool forgeEnabled = false; + private readonly int protocol; + private readonly bool forgeEnabled = false; /// /// Initialize the handler @@ -41,7 +37,7 @@ namespace MinecraftClient.Protocol.Handlers /// public PacketTypePalette GetTypeHandler() { - return GetTypeHandler(this.protocol); + return GetTypeHandler(protocol); } /// /// Get the packet type palette @@ -81,7 +77,7 @@ namespace MinecraftClient.Protocol.Handlers else p = new PacketPalette1192(); - p.SetForgeEnabled(this.forgeEnabled); + p.SetForgeEnabled(forgeEnabled); return p; } } diff --git a/MinecraftClient/Protocol/Handlers/PacketTypesIn.cs b/MinecraftClient/Protocol/Handlers/PacketTypesIn.cs index e9177243..4f7c5326 100644 --- a/MinecraftClient/Protocol/Handlers/PacketTypesIn.cs +++ b/MinecraftClient/Protocol/Handlers/PacketTypesIn.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MinecraftClient.Protocol.Handlers +namespace MinecraftClient.Protocol.Handlers { /// /// Incomming packet types diff --git a/MinecraftClient/Protocol/Handlers/PacketTypesOut.cs b/MinecraftClient/Protocol/Handlers/PacketTypesOut.cs index a2e8eecc..4c1d3346 100644 --- a/MinecraftClient/Protocol/Handlers/PacketTypesOut.cs +++ b/MinecraftClient/Protocol/Handlers/PacketTypesOut.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MinecraftClient.Protocol.Handlers +namespace MinecraftClient.Protocol.Handlers { /// /// Outgoing packet types diff --git a/MinecraftClient/Protocol/Handlers/Protocol16.cs b/MinecraftClient/Protocol/Handlers/Protocol16.cs index 4c8542e7..60a2df72 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol16.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol16.cs @@ -1,17 +1,17 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Net.Sockets; +using System.Security.Cryptography; +using System.Text; using System.Threading; using MinecraftClient.Crypto; -using MinecraftClient.Proxy; -using System.Security.Cryptography; -using MinecraftClient.Mapping; using MinecraftClient.Inventory; +using MinecraftClient.Mapping; using MinecraftClient.Protocol.Keys; -using MinecraftClient.Protocol.Session; using MinecraftClient.Protocol.Message; +using MinecraftClient.Protocol.Session; +using MinecraftClient.Proxy; namespace MinecraftClient.Protocol.Handlers { @@ -21,23 +21,23 @@ namespace MinecraftClient.Protocol.Handlers class Protocol16Handler : IMinecraftCom { - IMinecraftComHandler handler; + readonly IMinecraftComHandler handler; private bool autocomplete_received = false; private string autocomplete_result = ""; private bool encrypted = false; - private int protocolversion; + private readonly int protocolversion; private Tuple? netRead = null; - Crypto.AesCfb8Stream s; - TcpClient c; + Crypto.AesCfb8Stream? s; + readonly TcpClient c; public Protocol16Handler(TcpClient Client, int ProtocolVersion, IMinecraftComHandler Handler) { ConsoleIO.SetAutoCompleteEngine(this); if (protocolversion >= 72) ChatParser.InitTranslations(); - this.c = Client; - this.protocolversion = ProtocolVersion; - this.handler = Handler; + c = Client; + protocolversion = ProtocolVersion; + handler = Handler; if (Handler.GetTerrainEnabled()) { @@ -58,9 +58,12 @@ namespace MinecraftClient.Protocol.Handlers } } +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + // "IMinecraftComHandler handler" will not be used here. private Protocol16Handler(TcpClient Client) +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. { - this.c = Client; + c = Client; } private void Updater(object? o) @@ -94,15 +97,15 @@ namespace MinecraftClient.Protocol.Handlers bool connection_ok = true; while (c.Client.Available > 0 && connection_ok) { - byte id = readNextByte(); - connection_ok = processPacket(id); + byte id = ReadNextByte(); + connection_ok = ProcessPacket(id); } return connection_ok; } - private bool processPacket(byte id) + private bool ProcessPacket(byte id) { - int nbr = 0; + int nbr; switch (id) { case 0x00: @@ -110,98 +113,98 @@ namespace MinecraftClient.Protocol.Handlers Receive(keepalive, 1, 4, SocketFlags.None); handler.OnServerKeepAlive(); Send(keepalive); break; - case 0x01: readData(4); readNextString(); readData(5); break; - case 0x02: readData(1); readNextString(); readNextString(); readData(4); break; + case 0x01: ReadData(4); ReadNextString(); ReadData(5); break; + case 0x02: ReadData(1); ReadNextString(); ReadNextString(); ReadData(4); break; case 0x03: - string message = readNextString(); + string message = ReadNextString(); handler.OnTextReceived(new ChatMessage(message, protocolversion >= 72, 0, Guid.Empty)); break; - case 0x04: readData(16); break; - case 0x05: readData(6); readNextItemSlot(); break; - case 0x06: readData(12); break; - case 0x07: readData(9); break; - case 0x08: if (protocolversion >= 72) { readData(10); } else readData(8); break; - case 0x09: readData(8); readNextString(); break; - case 0x0A: readData(1); break; - case 0x0B: readData(33); break; - case 0x0C: readData(9); break; - case 0x0D: readData(41); break; - case 0x0E: readData(11); break; - case 0x0F: readData(10); readNextItemSlot(); readData(3); break; - case 0x10: readData(2); break; - case 0x11: readData(14); break; - case 0x12: readData(5); break; - case 0x13: if (protocolversion >= 72) { readData(9); } else readData(5); break; - case 0x14: readData(4); readNextString(); readData(16); readNextEntityMetaData(); break; - case 0x16: readData(8); break; - case 0x17: readData(19); readNextObjectData(); break; - case 0x18: readData(26); readNextEntityMetaData(); break; - case 0x19: readData(4); readNextString(); readData(16); break; - case 0x1A: readData(18); break; - case 0x1B: if (protocolversion >= 72) { readData(10); } break; - case 0x1C: readData(10); break; - case 0x1D: nbr = (int)readNextByte(); readData(nbr * 4); break; - case 0x1E: readData(4); break; - case 0x1F: readData(7); break; - case 0x20: readData(6); break; - case 0x21: readData(9); break; - case 0x22: readData(18); break; - case 0x23: readData(5); break; - case 0x26: readData(5); break; - case 0x27: if (protocolversion >= 72) { readData(9); } else readData(8); break; - case 0x28: readData(4); readNextEntityMetaData(); break; - case 0x29: readData(8); break; - case 0x2A: readData(5); break; - case 0x2B: readData(8); break; - case 0x2C: if (protocolversion >= 72) { readNextEntityProperties(protocolversion); } break; - case 0x33: readData(13); nbr = readNextInt(); readData(nbr); break; - case 0x34: readData(10); nbr = readNextInt(); readData(nbr); break; - case 0x35: readData(12); break; - case 0x36: readData(14); break; - case 0x37: readData(17); break; - case 0x38: readNextChunkBulkData(); break; - case 0x3C: readData(28); nbr = readNextInt(); readData(3 * nbr); readData(12); break; - case 0x3D: readData(18); break; - case 0x3E: readNextString(); readData(17); break; - case 0x3F: if (protocolversion > 51) { readNextString(); readData(32); } break; - case 0x46: readData(2); break; - case 0x47: readData(17); break; - case 0x64: readNextWindowData(protocolversion); break; - case 0x65: readData(1); break; - case 0x66: readData(7); readNextItemSlot(); break; - case 0x67: readData(3); readNextItemSlot(); break; - case 0x68: readData(1); for (nbr = readNextShort(); nbr > 0; nbr--) { readNextItemSlot(); } break; - case 0x69: readData(5); break; - case 0x6A: readData(4); break; - case 0x6B: readData(2); readNextItemSlot(); break; - case 0x6C: readData(2); break; - case 0x82: readData(10); readNextString(); readNextString(); readNextString(); readNextString(); break; - case 0x83: readData(4); nbr = readNextShort(); readData(nbr); break; - case 0x84: readData(11); nbr = readNextShort(); if (nbr > 0) { readData(nbr); } break; - case 0x85: if (protocolversion >= 74) { readData(13); } break; + case 0x04: ReadData(16); break; + case 0x05: ReadData(6); ReadNextItemSlot(); break; + case 0x06: ReadData(12); break; + case 0x07: ReadData(9); break; + case 0x08: if (protocolversion >= 72) { ReadData(10); } else ReadData(8); break; + case 0x09: ReadData(8); ReadNextString(); break; + case 0x0A: ReadData(1); break; + case 0x0B: ReadData(33); break; + case 0x0C: ReadData(9); break; + case 0x0D: ReadData(41); break; + case 0x0E: ReadData(11); break; + case 0x0F: ReadData(10); ReadNextItemSlot(); ReadData(3); break; + case 0x10: ReadData(2); break; + case 0x11: ReadData(14); break; + case 0x12: ReadData(5); break; + case 0x13: if (protocolversion >= 72) { ReadData(9); } else ReadData(5); break; + case 0x14: ReadData(4); ReadNextString(); ReadData(16); ReadNextEntityMetaData(); break; + case 0x16: ReadData(8); break; + case 0x17: ReadData(19); ReadNextObjectData(); break; + case 0x18: ReadData(26); ReadNextEntityMetaData(); break; + case 0x19: ReadData(4); ReadNextString(); ReadData(16); break; + case 0x1A: ReadData(18); break; + case 0x1B: if (protocolversion >= 72) { ReadData(10); } break; + case 0x1C: ReadData(10); break; + case 0x1D: nbr = (int)ReadNextByte(); ReadData(nbr * 4); break; + case 0x1E: ReadData(4); break; + case 0x1F: ReadData(7); break; + case 0x20: ReadData(6); break; + case 0x21: ReadData(9); break; + case 0x22: ReadData(18); break; + case 0x23: ReadData(5); break; + case 0x26: ReadData(5); break; + case 0x27: if (protocolversion >= 72) { ReadData(9); } else ReadData(8); break; + case 0x28: ReadData(4); ReadNextEntityMetaData(); break; + case 0x29: ReadData(8); break; + case 0x2A: ReadData(5); break; + case 0x2B: ReadData(8); break; + case 0x2C: if (protocolversion >= 72) { ReadNextEntityProperties(protocolversion); } break; + case 0x33: ReadData(13); nbr = ReadNextInt(); ReadData(nbr); break; + case 0x34: ReadData(10); nbr = ReadNextInt(); ReadData(nbr); break; + case 0x35: ReadData(12); break; + case 0x36: ReadData(14); break; + case 0x37: ReadData(17); break; + case 0x38: ReadNextChunkBulkData(); break; + case 0x3C: ReadData(28); nbr = ReadNextInt(); ReadData(3 * nbr); ReadData(12); break; + case 0x3D: ReadData(18); break; + case 0x3E: ReadNextString(); ReadData(17); break; + case 0x3F: if (protocolversion > 51) { ReadNextString(); ReadData(32); } break; + case 0x46: ReadData(2); break; + case 0x47: ReadData(17); break; + case 0x64: ReadNextWindowData(protocolversion); break; + case 0x65: ReadData(1); break; + case 0x66: ReadData(7); ReadNextItemSlot(); break; + case 0x67: ReadData(3); ReadNextItemSlot(); break; + case 0x68: ReadData(1); for (nbr = ReadNextShort(); nbr > 0; nbr--) { ReadNextItemSlot(); } break; + case 0x69: ReadData(5); break; + case 0x6A: ReadData(4); break; + case 0x6B: ReadData(2); ReadNextItemSlot(); break; + case 0x6C: ReadData(2); break; + case 0x82: ReadData(10); ReadNextString(); ReadNextString(); ReadNextString(); ReadNextString(); break; + case 0x83: ReadData(4); nbr = ReadNextShort(); ReadData(nbr); break; + case 0x84: ReadData(11); nbr = ReadNextShort(); if (nbr > 0) { ReadData(nbr); } break; + case 0x85: if (protocolversion >= 74) { ReadData(13); } break; case 0xC8: - if (readNextInt() == 2022) { Translations.WriteLogLine("mcc.player_dead"); } - if (protocolversion >= 72) { readData(4); } else readData(1); + if (ReadNextInt() == 2022) { Translations.WriteLogLine("mcc.player_dead"); } + if (protocolversion >= 72) { ReadData(4); } else ReadData(1); break; case 0xC9: - string name = readNextString(); bool online = readNextByte() != 0x00; readData(2); - Guid FakeUUID = new Guid(MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(name)).Take(16).ToArray()); + string name = ReadNextString(); bool online = ReadNextByte() != 0x00; ReadData(2); + Guid FakeUUID = new(MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(name)).Take(16).ToArray()); if (online) { handler.OnPlayerJoin(new PlayerInfo(name, FakeUUID)); } else { handler.OnPlayerLeave(FakeUUID); } break; - case 0xCA: if (protocolversion >= 72) { readData(9); } else readData(3); break; - case 0xCB: autocomplete_result = readNextString(); autocomplete_received = true; break; - case 0xCC: readNextString(); readData(4); break; - case 0xCD: readData(1); break; - case 0xCE: if (protocolversion > 51) { readNextString(); readNextString(); readData(1); } break; - case 0xCF: if (protocolversion > 51) { readNextString(); readData(1); readNextString(); } readData(4); break; - case 0xD0: if (protocolversion > 51) { readData(1); readNextString(); } break; - case 0xD1: if (protocolversion > 51) { readNextTeamData(); } break; + case 0xCA: if (protocolversion >= 72) { ReadData(9); } else ReadData(3); break; + case 0xCB: autocomplete_result = ReadNextString(); autocomplete_received = true; break; + case 0xCC: ReadNextString(); ReadData(4); break; + case 0xCD: ReadData(1); break; + case 0xCE: if (protocolversion > 51) { ReadNextString(); ReadNextString(); ReadData(1); } break; + case 0xCF: if (protocolversion > 51) { ReadNextString(); ReadData(1); ReadNextString(); } ReadData(4); break; + case 0xD0: if (protocolversion > 51) { ReadData(1); ReadNextString(); } break; + case 0xD1: if (protocolversion > 51) { ReadNextTeamData(); } break; case 0xFA: - string channel = readNextString(); - byte[] payload = readNextByteArray(); + string channel = ReadNextString(); + byte[] payload = ReadNextByteArray(); handler.OnPluginChannelMessage(channel, payload); break; case 0xFF: - string reason = readNextString(); + string reason = ReadNextString(); handler.OnConnectionLost(ChatBot.DisconnectReason.InGameKick, reason); break; default: return false; //unknown packet! } @@ -237,7 +240,7 @@ namespace MinecraftClient.Protocol.Handlers catch { } } - private void readData(int offset) + private void ReadData(int offset) { if (offset > 0) { @@ -250,9 +253,9 @@ namespace MinecraftClient.Protocol.Handlers } } - private string readNextString() + private string ReadNextString() { - ushort length = (ushort)readNextShort(); + ushort length = (ushort)ReadNextShort(); if (length > 0) { byte[] cache = new byte[length * 2]; @@ -267,15 +270,15 @@ namespace MinecraftClient.Protocol.Handlers return false; } - private byte[] readNextByteArray() + private byte[] ReadNextByteArray() { - short len = readNextShort(); + short len = ReadNextShort(); byte[] data = new byte[len]; Receive(data, 0, len, SocketFlags.None); return data; } - private short readNextShort() + private short ReadNextShort() { byte[] tmp = new byte[2]; Receive(tmp, 0, 2, SocketFlags.None); @@ -283,7 +286,7 @@ namespace MinecraftClient.Protocol.Handlers return BitConverter.ToInt16(tmp, 0); } - private int readNextInt() + private int ReadNextInt() { byte[] tmp = new byte[4]; Receive(tmp, 0, 4, SocketFlags.None); @@ -291,28 +294,28 @@ namespace MinecraftClient.Protocol.Handlers return BitConverter.ToInt32(tmp, 0); } - private byte readNextByte() + private byte ReadNextByte() { byte[] result = new byte[1]; Receive(result, 0, 1, SocketFlags.None); return result[0]; } - private void readNextItemSlot() + private void ReadNextItemSlot() { - short itemid = readNextShort(); + short itemid = ReadNextShort(); //If slot not empty (item ID != -1) if (itemid != -1) { - readData(1); //Item count - readData(2); //Item damage - short length = readNextShort(); + ReadData(1); //Item count + ReadData(2); //Item damage + short length = ReadNextShort(); //If length of optional NBT data > 0, read it - if (length > 0) { readData(length); } + if (length > 0) { ReadData(length); } } } - private void readNextEntityMetaData() + private void ReadNextEntityMetaData() { do { @@ -323,100 +326,100 @@ namespace MinecraftClient.Protocol.Handlers int type = id[0] >> 5; switch (type) { - case 0: readData(1); break; //Byte - case 1: readData(2); break; //Short - case 2: readData(4); break; //Int - case 3: readData(4); break; //Float - case 4: readNextString(); break; //String - case 5: readNextItemSlot(); break; //Slot - case 6: readData(12); break; //Vector (3 Int) + case 0: ReadData(1); break; //Byte + case 1: ReadData(2); break; //Short + case 2: ReadData(4); break; //Int + case 3: ReadData(4); break; //Float + case 4: ReadNextString(); break; //String + case 5: ReadNextItemSlot(); break; //Slot + case 6: ReadData(12); break; //Vector (3 Int) } } while (true); } - private void readNextObjectData() + private void ReadNextObjectData() { - int id = readNextInt(); - if (id != 0) { readData(6); } + int id = ReadNextInt(); + if (id != 0) { ReadData(6); } } - private void readNextTeamData() + private void ReadNextTeamData() { - readNextString(); //Internal Name - byte mode = readNextByte(); + ReadNextString(); //Internal Name + byte mode = ReadNextByte(); if (mode == 0 || mode == 2) { - readNextString(); //Display Name - readNextString(); //Prefix - readNextString(); //Suffix - readData(1); //Friendly Fire + ReadNextString(); //Display Name + ReadNextString(); //Prefix + ReadNextString(); //Suffix + ReadData(1); //Friendly Fire } if (mode == 0 || mode == 3 || mode == 4) { - short count = readNextShort(); + short count = ReadNextShort(); for (int i = 0; i < count; i++) { - readNextString(); //Players + ReadNextString(); //Players } } } - private void readNextEntityProperties(int protocolversion) + private void ReadNextEntityProperties(int protocolversion) { if (protocolversion >= 72) { if (protocolversion >= 74) { //Minecraft 1.6.2 - readNextInt(); //Entity ID - int count = readNextInt(); + ReadNextInt(); //Entity ID + int count = ReadNextInt(); for (int i = 0; i < count; i++) { - readNextString(); //Property name - readData(8); //Property value (Double) - short othercount = readNextShort(); - readData(25 * othercount); + ReadNextString(); //Property name + ReadData(8); //Property value (Double) + short othercount = ReadNextShort(); + ReadData(25 * othercount); } } else { //Minecraft 1.6.0 / 1.6.1 - readNextInt(); //Entity ID - int count = readNextInt(); + ReadNextInt(); //Entity ID + int count = ReadNextInt(); for (int i = 0; i < count; i++) { - readNextString(); //Property name - readData(8); //Property value (Double) + ReadNextString(); //Property name + ReadData(8); //Property value (Double) } } } } - private void readNextWindowData(int protocolversion) + private void ReadNextWindowData(int protocolversion) { - readData(1); - byte windowtype = readNextByte(); - readNextString(); - readData(1); + ReadData(1); + byte windowtype = ReadNextByte(); + ReadNextString(); + ReadData(1); if (protocolversion > 51) { - readData(1); + ReadData(1); if (protocolversion >= 72 && windowtype == 0xb) { - readNextInt(); + ReadNextInt(); } } } - private void readNextChunkBulkData() + private void ReadNextChunkBulkData() { - short chunkcount = readNextShort(); - int datalen = readNextInt(); - readData(1); - readData(datalen); - readData(12 * (chunkcount)); + short chunkcount = ReadNextShort(); + int datalen = ReadNextInt(); + ReadData(1); + ReadData(datalen); + ReadData(12 * (chunkcount)); } private void Receive(byte[] buffer, int start, int offset, SocketFlags f) @@ -425,20 +428,18 @@ namespace MinecraftClient.Protocol.Handlers while (read < offset) { if (encrypted) - { - read += s.Read(buffer, start + read, offset - read); - } - else read += c.Client.Receive(buffer, start + read, offset - read, f); + read += s!.Read(buffer, start + read, offset - read); + else + read += c.Client.Receive(buffer, start + read, offset - read, f); } } private void Send(byte[] buffer) { if (encrypted) - { - s.Write(buffer, 0, buffer.Length); - } - else c.Client.Send(buffer); + s!.Write(buffer, 0, buffer.Length); + else + c.Client.Send(buffer); } private bool Handshake(string uuid, string username, string sessionID, string host, int port, SessionToken session) @@ -481,14 +482,14 @@ namespace MinecraftClient.Protocol.Handlers Receive(pid, 0, 1, SocketFlags.None); while (pid[0] == 0xFA) //Skip some early plugin messages { - processPacket(pid[0]); + ProcessPacket(pid[0]); Receive(pid, 0, 1, SocketFlags.None); } if (pid[0] == 0xFD) { - string serverID = readNextString(); - byte[] PublicServerkey = readNextByteArray(); - byte[] token = readNextByteArray(); + string serverID = ReadNextString(); + byte[] PublicServerkey = ReadNextByteArray(); + byte[] token = ReadNextByteArray(); if (serverID == "-") Translations.WriteLineFormatted("mcc.server_offline"); @@ -506,7 +507,7 @@ namespace MinecraftClient.Protocol.Handlers private bool StartEncryption(string uuid, string username, string sessionID, byte[] token, string serverIDhash, byte[] serverPublicKey, SessionToken session) { - RSACryptoServiceProvider RSAService = CryptoHandler.DecodeRSAPublicKey(serverPublicKey); + RSACryptoServiceProvider RSAService = CryptoHandler.DecodeRSAPublicKey(serverPublicKey)!; byte[] secretKey = CryptoHandler.ClientAESPrivateKey ?? CryptoHandler.GenerateAESPrivateKey(); if (Settings.DebugMessages) @@ -515,7 +516,7 @@ namespace MinecraftClient.Protocol.Handlers if (serverIDhash != "-") { Translations.WriteLine("mcc.session"); - string serverHash = CryptoHandler.getServerHash(serverIDhash, serverPublicKey, secretKey); + string serverHash = CryptoHandler.GetServerHash(serverIDhash, serverPublicKey, secretKey); bool needCheckSession = true; if (session.ServerPublicKey != null && session.SessionPreCheckTask != null @@ -568,7 +569,7 @@ namespace MinecraftClient.Protocol.Handlers Receive(pid, 0, 1, SocketFlags.None); if (pid[0] == 0xFC) { - readData(4); + ReadData(4); s = new AesCfb8Stream(c.GetStream(), secretKey); encrypted = true; return true; @@ -595,18 +596,18 @@ namespace MinecraftClient.Protocol.Handlers Receive(pid, 0, 1, SocketFlags.None); while (pid[0] >= 0xC0 && pid[0] != 0xFF) //Skip some early packets or plugin messages { - processPacket(pid[0]); + ProcessPacket(pid[0]); Receive(pid, 0, 1, SocketFlags.None); } if (pid[0] == (byte)1) { - readData(4); readNextString(); readData(5); + ReadData(4); ReadNextString(); ReadData(5); StartUpdating(); return true; //The Server accepted the request } else if (pid[0] == (byte)0xFF) { - string reason = readNextString(); + string reason = ReadNextString(); handler.OnConnectionLost(ChatBot.DisconnectReason.LoginRejected, reason); return false; } @@ -804,7 +805,7 @@ namespace MinecraftClient.Protocol.Handlers byte[] dataLength = BitConverter.GetBytes((short)data.Length); Array.Reverse(dataLength); - Send(concatBytes(new byte[] { 0xFA }, channelLength, channelData, dataLength, data)); + Send(ConcatBytes(new byte[] { 0xFA }, channelLength, channelData, dataLength, data)); return true; } @@ -815,7 +816,7 @@ namespace MinecraftClient.Protocol.Handlers IEnumerable IAutoComplete.AutoComplete(string BehindCursor) { if (String.IsNullOrEmpty(BehindCursor)) - return new string[] { }; + return Array.Empty(); byte[] autocomplete = new byte[3 + (BehindCursor.Length * 2)]; autocomplete[0] = 0xCB; @@ -835,20 +836,20 @@ namespace MinecraftClient.Protocol.Handlers return autocomplete_result.Split((char)0x00); } - private static byte[] concatBytes(params byte[][] bytes) + private static byte[] ConcatBytes(params byte[][] bytes) { - List result = new List(); + List result = new(); foreach (byte[] array in bytes) result.AddRange(array); return result.ToArray(); } - public static bool doPing(string host, int port, ref int protocolversion) + public static bool DoPing(string host, int port, ref int protocolversion) { try { string version = ""; - TcpClient tcp = ProxyHandler.newTcpClient(host, port); + TcpClient tcp = ProxyHandler.NewTcpClient(host, port); tcp.ReceiveTimeout = 30000; // 30 seconds tcp.ReceiveTimeout = 5000; //MC 1.7.2+ SpigotMC servers won't respond, so we need a reasonable timeout. byte[] ping = new byte[2] { 0xfe, 0x01 }; @@ -857,8 +858,8 @@ namespace MinecraftClient.Protocol.Handlers if (ping[0] == 0xff) { - Protocol16Handler ComTmp = new Protocol16Handler(tcp); - string result = ComTmp.readNextString(); + Protocol16Handler ComTmp = new(tcp); + string result = ComTmp.ReadNextString(); if (Settings.DebugMessages) { diff --git a/MinecraftClient/Protocol/Handlers/Protocol18.cs b/MinecraftClient/Protocol/Handlers/Protocol18.cs index 93347a38..0ec192b4 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18.cs @@ -1,26 +1,26 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Net.Sockets; -using System.Threading; -using System.Security.Cryptography; -using System.Diagnostics; -using System.Text.RegularExpressions; using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Net.Sockets; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; using MinecraftClient.Crypto; -using MinecraftClient.Proxy; +using MinecraftClient.Inventory; +using MinecraftClient.Inventory.ItemPalettes; +using MinecraftClient.Logger; using MinecraftClient.Mapping; using MinecraftClient.Mapping.BlockPalettes; using MinecraftClient.Mapping.EntityPalettes; using MinecraftClient.Protocol.Handlers.Forge; -using MinecraftClient.Inventory; -using MinecraftClient.Inventory.ItemPalettes; using MinecraftClient.Protocol.Handlers.PacketPalettes; -using MinecraftClient.Logger; using MinecraftClient.Protocol.Keys; -using MinecraftClient.Protocol.Session; using MinecraftClient.Protocol.Message; +using MinecraftClient.Protocol.Session; +using MinecraftClient.Proxy; namespace MinecraftClient.Protocol.Handlers { @@ -63,44 +63,43 @@ namespace MinecraftClient.Protocol.Handlers private int compression_treshold = 0; private bool autocomplete_received = false; private int autocomplete_transaction_id = 0; - private readonly List autocomplete_result = new List(); - private readonly Dictionary window_actions = new Dictionary(); + private readonly List autocomplete_result = new(); + private readonly Dictionary window_actions = new(); private bool login_phase = true; - private int protocolVersion; + private readonly int protocolVersion; private int currentDimension; private bool isOnlineMode = false; private readonly BlockingCollection>> packetQueue = new(); private int pendingAcknowledgments = 0; - private LastSeenMessagesCollector lastSeenMessagesCollector = new(5); + private readonly LastSeenMessagesCollector lastSeenMessagesCollector = new(5); private LastSeenMessageList.Entry? lastReceivedMessage = null; - - Protocol18Forge pForge; - Protocol18Terrain pTerrain; - IMinecraftComHandler handler; - EntityPalette entityPalette; - ItemPalette itemPalette; - PacketTypePalette packetPalette; - SocketWrapper socketWrapper; - DataTypes dataTypes; + readonly Protocol18Forge pForge; + readonly Protocol18Terrain pTerrain; + readonly IMinecraftComHandler handler; + readonly EntityPalette entityPalette; + readonly ItemPalette itemPalette; + readonly PacketTypePalette packetPalette; + readonly SocketWrapper socketWrapper; + readonly DataTypes dataTypes; Tuple? netMain = null; // main thread Tuple? netReader = null; // reader thread - ILogger log; - RandomNumberGenerator randomGen; + readonly ILogger log; + readonly RandomNumberGenerator randomGen; - public Protocol18Handler(TcpClient Client, int protocolVersion, IMinecraftComHandler handler, ForgeInfo forgeInfo) + public Protocol18Handler(TcpClient Client, int protocolVersion, IMinecraftComHandler handler, ForgeInfo? forgeInfo) { ConsoleIO.SetAutoCompleteEngine(this); ChatParser.InitTranslations(); - this.socketWrapper = new SocketWrapper(Client); - this.dataTypes = new DataTypes(protocolVersion); + socketWrapper = new SocketWrapper(Client); + dataTypes = new DataTypes(protocolVersion); this.protocolVersion = protocolVersion; this.handler = handler; - this.pForge = new Protocol18Forge(forgeInfo, protocolVersion, dataTypes, this, handler); - this.pTerrain = new Protocol18Terrain(protocolVersion, dataTypes, handler); - this.packetPalette = new PacketTypeHandler(protocolVersion, forgeInfo != null).GetTypeHandler(); - this.log = handler.GetLogger(); - this.randomGen = RandomNumberGenerator.Create(); + pForge = new Protocol18Forge(forgeInfo, protocolVersion, dataTypes, this, handler); + pTerrain = new Protocol18Terrain(protocolVersion, dataTypes, handler); + packetPalette = new PacketTypeHandler(protocolVersion, forgeInfo != null).GetTypeHandler(); + log = handler.GetLogger(); + randomGen = RandomNumberGenerator.Create(); if (handler.GetTerrainEnabled() && protocolVersion > MC_1_19_2_Version) { @@ -335,7 +334,7 @@ namespace MinecraftClient.Protocol.Handlers case 0x04: int messageId = dataTypes.ReadNextVarInt(packetData); string channel = dataTypes.ReadNextString(packetData); - List responseData = new List(); + List responseData = new(); bool understood = pForge.HandleLoginPluginRequest(channel, packetData, ref responseData); SendLoginPluginResponse(messageId, understood, responseData.ToArray()); return understood; @@ -391,12 +390,12 @@ namespace MinecraftClient.Protocol.Handlers dimensionType = dataTypes.ReadNextNbt(packetData); // Dimension Type: NBT Tag Compound else dataTypes.ReadNextString(packetData); - this.currentDimension = 0; + currentDimension = 0; } else if (protocolVersion >= MC_1_9_1_Version) - this.currentDimension = dataTypes.ReadNextInt(packetData); + currentDimension = dataTypes.ReadNextInt(packetData); else - this.currentDimension = (sbyte)dataTypes.ReadNextByte(packetData); + currentDimension = (sbyte)dataTypes.ReadNextByte(packetData); if (protocolVersion < MC_1_14_Version) dataTypes.ReadNextByte(packetData); // Difficulty - 1.13 and below @@ -506,7 +505,7 @@ namespace MinecraftClient.Protocol.Handlers else { PlayerInfo? player = handler.GetPlayerInfo(senderUUID); - verifyResult = player == null ? false : player.VerifyMessage(signedChat, timestamp, salt, ref messageSignature); + verifyResult = player != null && player.VerifyMessage(signedChat, timestamp, salt, ref messageSignature); } ChatMessage chat = new(signedChat, true, messageType, senderUUID, unsignedChatContent, senderDisplayName, senderTeamName, timestamp, messageSignature, verifyResult); @@ -572,8 +571,8 @@ namespace MinecraftClient.Protocol.Handlers } ChatMessage chat = new(signedChat, false, chatTypeId, senderUUID, unsignedChatContent, senderDisplayName, senderTeamName, timestamp, headerSignature, verifyResult); - if (isOnlineMode && !chat.lacksSender()) - this.acknowledge(chat); + if (isOnlineMode && !chat.LacksSender()) + Acknowledge(chat); handler.OnTextReceived(chat); } break; @@ -618,11 +617,11 @@ namespace MinecraftClient.Protocol.Handlers dimensionTypeRespawn = dataTypes.ReadNextNbt(packetData); // Dimension Type: NBT Tag Compound else dataTypes.ReadNextString(packetData); - this.currentDimension = 0; + currentDimension = 0; } else { // 1.15 and below - this.currentDimension = dataTypes.ReadNextInt(packetData); + currentDimension = dataTypes.ReadNextInt(packetData); } if (protocolVersion >= MC_1_16_Version) @@ -816,7 +815,7 @@ namespace MinecraftClient.Protocol.Handlers List icons = new(); // 1,9 + = needs tracking position to be true to get the icons - if (protocolVersion > MC_1_9_Version ? trackingPosition : true) + if (protocolVersion <= MC_1_9_Version || trackingPosition) { iconcount = dataTypes.ReadNextVarInt(packetData); @@ -888,13 +887,13 @@ namespace MinecraftClient.Protocol.Handlers // MC 1.14 or greater int windowID = dataTypes.ReadNextVarInt(packetData); int size = dataTypes.ReadNextByte(packetData); - List trades = new List(); + List trades = new(); for (int tradeId = 0; tradeId < size; tradeId++) { VillagerTrade trade = dataTypes.ReadNextTrade(packetData, itemPalette); trades.Add(trade); } - VillagerInfo villagerInfo = new VillagerInfo() + VillagerInfo villagerInfo = new() { Level = dataTypes.ReadNextVarInt(packetData), Experience = dataTypes.ReadNextVarInt(packetData), @@ -980,7 +979,7 @@ namespace MinecraftClient.Protocol.Handlers int localZ = (int)((block >> 4) & 0x0F); int localY = (int)(block & 0x0F); - Block b = new Block((ushort)blockId); + Block b = new((ushort)blockId); int blockX = (sectionX * 16) + localX; int blockY = (sectionY * 16) + localY; int blockZ = (sectionZ * 16) + localZ; @@ -1017,7 +1016,7 @@ namespace MinecraftClient.Protocol.Handlers int blockX = locationXZ >> 4; int blockZ = locationXZ & 0x0F; - Block block = new Block(blockIdMeta); + Block block = new(blockIdMeta); handler.GetWorld().SetBlock(new Location(chunkX, chunkZ, blockX, blockY, blockZ), block); } } @@ -1159,6 +1158,7 @@ namespace MinecraftClient.Protocol.Handlers // Property: Tuple[]? properties = useProperty ? new Tuple[propNum] : null; for (int p = 0; p < propNum; p++) @@ -1171,6 +1171,7 @@ namespace MinecraftClient.Protocol.Handlers if (useProperty) properties![p] = new(propertyName, val, propertySignature); } +#pragma warning restore CS0162 // Unreachable code detected int gameMode = dataTypes.ReadNextVarInt(packetData); // Gamemode handler.OnGamemodeUpdate(uuid, gameMode); @@ -1233,7 +1234,7 @@ namespace MinecraftClient.Protocol.Handlers string name = dataTypes.ReadNextString(packetData); bool online = dataTypes.ReadNextBool(packetData); short ping = dataTypes.ReadNextShort(packetData); - Guid FakeUUID = new Guid(MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(name)).Take(16).ToArray()); + Guid FakeUUID = new(MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(name)).Take(16).ToArray()); if (online) handler.OnPlayerJoin(new PlayerInfo(name, FakeUUID)); else handler.OnPlayerLeave(FakeUUID); @@ -1288,7 +1289,7 @@ namespace MinecraftClient.Protocol.Handlers ContainerTypeOld inventoryType = (ContainerTypeOld)Enum.Parse(typeof(ContainerTypeOld), type); string title = dataTypes.ReadNextString(packetData); byte slots = dataTypes.ReadNextByte(packetData); - Container inventory = new Container(windowID, inventoryType, ChatParser.ParseText(title)); + Container inventory = new(windowID, inventoryType, ChatParser.ParseText(title)); handler.OnInventoryOpen(windowID, inventory); } else @@ -1297,7 +1298,7 @@ namespace MinecraftClient.Protocol.Handlers int windowID = dataTypes.ReadNextVarInt(packetData); int windowType = dataTypes.ReadNextVarInt(packetData); string title = dataTypes.ReadNextString(packetData); - Container inventory = new Container(windowID, windowType, ChatParser.ParseText(title)); + Container inventory = new(windowID, windowType, ChatParser.ParseText(title)); handler.OnInventoryOpen(windowID, inventory); } } @@ -1329,10 +1330,10 @@ namespace MinecraftClient.Protocol.Handlers dataTypes.ReadNextShort(packetData); } - Dictionary inventorySlots = new Dictionary(); + Dictionary inventorySlots = new(); for (int slotId = 0; slotId < elements; slotId++) { - Item item = dataTypes.ReadNextItemSlot(packetData, itemPalette); + Item? item = dataTypes.ReadNextItemSlot(packetData, itemPalette); if (item != null) inventorySlots[slotId] = item; } @@ -1351,7 +1352,7 @@ namespace MinecraftClient.Protocol.Handlers if (protocolVersion >= MC_1_17_1_Version) stateId = dataTypes.ReadNextVarInt(packetData); // State ID - 1.17.1 and above short slotID = dataTypes.ReadNextShort(packetData); - Item item = dataTypes.ReadNextItemSlot(packetData, itemPalette); + Item? item = dataTypes.ReadNextItemSlot(packetData, itemPalette); handler.OnSetSlot(windowID, slotID, item, stateId); } break; @@ -1382,7 +1383,7 @@ namespace MinecraftClient.Protocol.Handlers if (!url.StartsWith("http") && hash.Length != 40) // Some server may have null hash value break; //Send back "accepted" and "successfully loaded" responses for plugins or server config making use of resource pack mandatory - byte[] responseHeader = new byte[0]; + byte[] responseHeader = Array.Empty(); if (protocolVersion < MC_1_10_Version) //MC 1.10 does not include resource pack hash in responses responseHeader = dataTypes.ConcatBytes(dataTypes.GetVarInt(hash.Length), Encoding.UTF8.GetBytes(hash)); SendPacket(PacketTypesOut.ResourcePackStatus, dataTypes.ConcatBytes(responseHeader, dataTypes.GetVarInt(3))); //Accepted pack @@ -1406,16 +1407,16 @@ namespace MinecraftClient.Protocol.Handlers { byte bitsData = dataTypes.ReadNextByte(packetData); // Top bit set if another entry follows, and otherwise unset if this is the last item in the array - hasNext = (bitsData >> 7) == 1 ? true : false; + hasNext = (bitsData >> 7) == 1; int slot2 = bitsData >> 1; - Item item = dataTypes.ReadNextItemSlot(packetData, itemPalette); + Item? item = dataTypes.ReadNextItemSlot(packetData, itemPalette); handler.OnEntityEquipment(entityid, slot2, item); } while (hasNext); } else { int slot2 = dataTypes.ReadNextVarInt(packetData); - Item item = dataTypes.ReadNextItemSlot(packetData, itemPalette); + Item? item = dataTypes.ReadNextItemSlot(packetData, itemPalette); handler.OnEntityEquipment(entityid, slot2, item); } } @@ -1441,7 +1442,7 @@ namespace MinecraftClient.Protocol.Handlers byte Yaw = dataTypes.ReadNextByte(packetData); byte Pitch = dataTypes.ReadNextByte(packetData); - Location EntityLocation = new Location(X, Y, Z); + Location EntityLocation = new(X, Y, Z); handler.OnSpawnPlayer(EntityID, UUID, EntityLocation, Yaw, Pitch); } @@ -1495,9 +1496,9 @@ namespace MinecraftClient.Protocol.Handlers Double DeltaY = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); Double DeltaZ = Convert.ToDouble(dataTypes.ReadNextShort(packetData)); bool OnGround = dataTypes.ReadNextBool(packetData); - DeltaX = DeltaX / (128 * 32); - DeltaY = DeltaY / (128 * 32); - DeltaZ = DeltaZ / (128 * 32); + DeltaX /= (128 * 32); + DeltaY /= (128 * 32); + DeltaZ /= (128 * 32); handler.OnEntityPosition(EntityID, DeltaX, DeltaY, DeltaZ, OnGround); } break; @@ -1511,9 +1512,9 @@ namespace MinecraftClient.Protocol.Handlers byte _yaw = dataTypes.ReadNextByte(packetData); byte _pitch = dataTypes.ReadNextByte(packetData); bool OnGround = dataTypes.ReadNextBool(packetData); - DeltaX = DeltaX / (128 * 32); - DeltaY = DeltaY / (128 * 32); - DeltaZ = DeltaZ / (128 * 32); + DeltaX /= (128 * 32); + DeltaY /= (128 * 32); + DeltaZ /= (128 * 32); handler.OnEntityPosition(EntityID, DeltaX, DeltaY, DeltaZ, OnGround); } break; @@ -1522,15 +1523,15 @@ namespace MinecraftClient.Protocol.Handlers { int EntityID = dataTypes.ReadNextVarInt(packetData); int NumberOfProperties = protocolVersion >= MC_1_17_Version ? dataTypes.ReadNextVarInt(packetData) : dataTypes.ReadNextInt(packetData); - Dictionary keys = new Dictionary(); + Dictionary keys = new(); for (int i = 0; i < NumberOfProperties; i++) { string _key = dataTypes.ReadNextString(packetData); Double _value = dataTypes.ReadNextDouble(packetData); - List op0 = new List(); - List op1 = new List(); - List op2 = new List(); + List op0 = new(); + List op1 = new(); + List op2 = new(); int NumberOfModifiers = dataTypes.ReadNextVarInt(packetData); for (int j = 0; j < NumberOfModifiers; j++) { @@ -1716,13 +1717,17 @@ namespace MinecraftClient.Protocol.Handlers /// private void StartUpdating() { - Thread threadUpdater = new Thread(new ParameterizedThreadStart(Updater)); - threadUpdater.Name = "ProtocolPacketHandler"; + Thread threadUpdater = new(new ParameterizedThreadStart(Updater)) + { + Name = "ProtocolPacketHandler" + }; netMain = new Tuple(threadUpdater, new CancellationTokenSource()); threadUpdater.Start(netMain.Item2.Token); - Thread threadReader = new Thread(new ParameterizedThreadStart(PacketReader)); - threadReader.Name = "ProtocolPacketReader"; + Thread threadReader = new(new ParameterizedThreadStart(PacketReader)) + { + Name = "ProtocolPacketReader" + }; netReader = new Tuple(threadReader, new CancellationTokenSource()); threadReader.Start(netReader.Item2.Token); } @@ -1814,7 +1819,7 @@ namespace MinecraftClient.Protocol.Handlers byte[] handshake_packet = dataTypes.ConcatBytes(protocol_version, dataTypes.GetString(server_address), server_port, next_state); SendPacket(0x00, handshake_packet); - List fullLoginPacket = new List(); + List fullLoginPacket = new(); fullLoginPacket.AddRange(dataTypes.GetString(handler.GetUsername())); // Username if (protocolVersion >= MC_1_19_Version) { @@ -1854,7 +1859,7 @@ namespace MinecraftClient.Protocol.Handlers } else if (packetID == 0x01) //Encryption request { - this.isOnlineMode = true; + isOnlineMode = true; string serverID = dataTypes.ReadNextString(packetData); byte[] serverPublicKey = dataTypes.ReadNextByteArray(packetData); byte[] token = dataTypes.ReadNextByteArray(packetData); @@ -1884,7 +1889,7 @@ namespace MinecraftClient.Protocol.Handlers /// True if encryption was successful private bool StartEncryption(string uuid, string sessionID, byte[] token, string serverIDhash, byte[] serverPublicKey, PlayerKeyPair? playerKeyPair, SessionToken session) { - RSACryptoServiceProvider RSAService = CryptoHandler.DecodeRSAPublicKey(serverPublicKey); + RSACryptoServiceProvider RSAService = CryptoHandler.DecodeRSAPublicKey(serverPublicKey)!; byte[] secretKey = CryptoHandler.ClientAESPrivateKey ?? CryptoHandler.GenerateAESPrivateKey(); log.Debug(Translations.Get("debug.crypto")); @@ -1904,7 +1909,7 @@ namespace MinecraftClient.Protocol.Handlers if (needCheckSession) { - string serverHash = CryptoHandler.getServerHash(serverIDhash, serverPublicKey, secretKey); + string serverHash = CryptoHandler.GetServerHash(serverIDhash, serverPublicKey, secretKey); if (ProtocolHandler.SessionCheck(uuid, sessionID, serverHash)) { @@ -2020,13 +2025,13 @@ namespace MinecraftClient.Protocol.Handlers { if (String.IsNullOrEmpty(BehindCursor)) - return new string[] { }; + return Array.Empty(); byte[] transaction_id = dataTypes.GetVarInt(autocomplete_transaction_id); byte[] assume_command = new byte[] { 0x00 }; byte[] has_position = new byte[] { 0x00 }; - byte[] tabcomplete_packet = new byte[] { }; + byte[] tabcomplete_packet = Array.Empty(); if (protocolVersion >= MC_1_8_Version) { @@ -2058,12 +2063,13 @@ namespace MinecraftClient.Protocol.Handlers SendPacket(PacketTypesOut.TabComplete, tabcomplete_packet); int wait_left = 50; //do not wait more than 5 seconds (50 * 100 ms) - Thread t1 = new Thread(new ThreadStart(delegate - { - while (wait_left > 0 && !autocomplete_received) { System.Threading.Thread.Sleep(100); wait_left--; } - if (autocomplete_result.Count > 0) - ConsoleIO.WriteLineFormatted("§8" + String.Join(" ", autocomplete_result), false); - })); + ThreadStart start = new(delegate + { + while (wait_left > 0 && !autocomplete_received) { System.Threading.Thread.Sleep(100); wait_left--; } + if (autocomplete_result.Count > 0) + ConsoleIO.WriteLineFormatted("§8" + String.Join(" ", autocomplete_result), false); + }); + Thread t1 = new(start); t1.Start(); return autocomplete_result; } @@ -2072,14 +2078,14 @@ namespace MinecraftClient.Protocol.Handlers /// Ping a Minecraft server to get information about the server /// /// True if ping was successful - public static bool doPing(string host, int port, ref int protocolVersion, ref ForgeInfo? forgeInfo) + public static bool DoPing(string host, int port, ref int protocolVersion, ref ForgeInfo? forgeInfo) { string version = ""; - TcpClient tcp = ProxyHandler.newTcpClient(host, port); + TcpClient tcp = ProxyHandler.NewTcpClient(host, port); tcp.ReceiveTimeout = 30000; // 30 seconds tcp.ReceiveBufferSize = 1024 * 1024; - SocketWrapper socketWrapper = new SocketWrapper(tcp); - DataTypes dataTypes = new DataTypes(MC_1_8_Version); + SocketWrapper socketWrapper = new(tcp); + DataTypes dataTypes = new(MC_1_8_Version); byte[] packet_id = dataTypes.GetVarInt(0); byte[] protocol_version = dataTypes.GetVarInt(-1); @@ -2098,7 +2104,7 @@ namespace MinecraftClient.Protocol.Handlers int packetLength = dataTypes.ReadNextVarIntRAW(socketWrapper); if (packetLength > 0) //Read Response length { - Queue packetData = new Queue(socketWrapper.ReadDataRAW(packetLength)); + Queue packetData = new(socketWrapper.ReadDataRAW(packetLength)); if (dataTypes.ReadNextVarInt(packetData) == 0x00) //Read Packet ID { string result = dataTypes.ReadNextString(packetData); //Get the Json data @@ -2182,15 +2188,15 @@ namespace MinecraftClient.Protocol.Handlers catch (ObjectDisposedException) { return false; } } - public LastSeenMessageList.Acknowledgment consumeAcknowledgment() + public LastSeenMessageList.Acknowledgment ConsumeAcknowledgment() { - this.pendingAcknowledgments = 0; - return new LastSeenMessageList.Acknowledgment(this.lastSeenMessagesCollector.GetLastSeenMessages(), this.lastReceivedMessage); + pendingAcknowledgments = 0; + return new LastSeenMessageList.Acknowledgment(lastSeenMessagesCollector.GetLastSeenMessages(), lastReceivedMessage); } - public void acknowledge(ChatMessage message) + public void Acknowledge(ChatMessage message) { - LastSeenMessageList.Entry? entry = message.toLastSeenMessageEntry(); + LastSeenMessageList.Entry? entry = message.ToLastSeenMessageEntry(); if (entry != null) { @@ -2198,7 +2204,7 @@ namespace MinecraftClient.Protocol.Handlers lastReceivedMessage = null; if (pendingAcknowledgments++ > 64) - SendMessageAcknowledgment(this.consumeAcknowledgment()); + SendMessageAcknowledgment(ConsumeAcknowledgment()); } } @@ -2272,7 +2278,7 @@ namespace MinecraftClient.Protocol.Handlers try { LastSeenMessageList.Acknowledgment? acknowledgment = - (protocolVersion >= MC_1_19_2_Version) ? this.consumeAcknowledgment() : null; + (protocolVersion >= MC_1_19_2_Version) ? ConsumeAcknowledgment() : null; List fields = new(); @@ -2349,7 +2355,7 @@ namespace MinecraftClient.Protocol.Handlers if (protocolVersion >= MC_1_19_Version) { LastSeenMessageList.Acknowledgment? acknowledgment = - (protocolVersion >= MC_1_19_2_Version) ? this.consumeAcknowledgment() : null; + (protocolVersion >= MC_1_19_2_Version) ? ConsumeAcknowledgment() : null; // Timestamp: Instant(Long) DateTimeOffset timeNow = DateTimeOffset.UtcNow; @@ -2396,7 +2402,7 @@ namespace MinecraftClient.Protocol.Handlers { try { - List fields = new List(); + List fields = new(); fields.AddRange(dataTypes.GetVarInt(PlayerEntityID)); fields.AddRange(dataTypes.GetVarInt(ActionID)); fields.AddRange(dataTypes.GetVarInt(0)); @@ -2460,7 +2466,7 @@ namespace MinecraftClient.Protocol.Handlers { try { - List fields = new List(); + List fields = new(); fields.AddRange(dataTypes.GetString(language)); fields.Add(viewDistance); @@ -2507,7 +2513,7 @@ namespace MinecraftClient.Protocol.Handlers { if (handler.GetTerrainEnabled()) { - byte[] yawpitch = new byte[0]; + byte[] yawpitch = Array.Empty(); PacketTypesOut packetType = PacketTypesOut.PlayerPosition; if (yaw.HasValue && pitch.HasValue) @@ -2523,7 +2529,7 @@ namespace MinecraftClient.Protocol.Handlers dataTypes.GetDouble(location.Y), protocolVersion < MC_1_8_Version ? dataTypes.GetDouble(location.Y + 1.62) - : new byte[0], + : Array.Empty(), dataTypes.GetDouble(location.Z), yawpitch, new byte[] { onGround ? (byte)1 : (byte)0 })); @@ -2595,7 +2601,7 @@ namespace MinecraftClient.Protocol.Handlers { try { - List fields = new List(); + List fields = new(); fields.AddRange(dataTypes.GetVarInt(EntityID)); fields.AddRange(dataTypes.GetVarInt(type)); @@ -2618,7 +2624,7 @@ namespace MinecraftClient.Protocol.Handlers { try { - List fields = new List(); + List fields = new(); fields.AddRange(dataTypes.GetVarInt(EntityID)); fields.AddRange(dataTypes.GetVarInt(type)); fields.AddRange(dataTypes.GetFloat(X)); @@ -2641,7 +2647,7 @@ namespace MinecraftClient.Protocol.Handlers { try { - List fields = new List(); + List fields = new(); fields.AddRange(dataTypes.GetVarInt(EntityID)); fields.AddRange(dataTypes.GetVarInt(type)); fields.AddRange(dataTypes.GetVarInt(hand)); @@ -2671,7 +2677,7 @@ namespace MinecraftClient.Protocol.Handlers // TODO once Player Block Placement is implemented for older versions try { - List packet = new List(); + List packet = new(); packet.AddRange(dataTypes.GetVarInt(hand)); if (protocolVersion >= MC_1_19_Version) packet.AddRange(dataTypes.GetVarInt(sequenceId)); @@ -2687,7 +2693,7 @@ namespace MinecraftClient.Protocol.Handlers { try { - List packet = new List(); + List packet = new(); packet.AddRange(dataTypes.GetVarInt(status)); packet.AddRange(dataTypes.GetLocation(location)); packet.AddRange(dataTypes.GetVarInt(dataTypes.GetBlockFace(face))); @@ -2707,7 +2713,7 @@ namespace MinecraftClient.Protocol.Handlers return false; // NOT IMPLEMENTED for older MC versions try { - List packet = new List(); + List packet = new(); packet.AddRange(dataTypes.GetVarInt(hand)); packet.AddRange(dataTypes.GetLocation(location)); packet.AddRange(dataTypes.GetVarInt(dataTypes.GetBlockFace(face))); @@ -2729,7 +2735,7 @@ namespace MinecraftClient.Protocol.Handlers { try { - List packet = new List(); + List packet = new(); packet.AddRange(dataTypes.GetShort(slot)); SendPacket(PacketTypesOut.HeldItemChange, packet); return true; @@ -2774,8 +2780,10 @@ namespace MinecraftClient.Protocol.Handlers case WindowActionType.AddDragMiddle: button = 9; mode = 5; item = new Item(ItemType.Null, 0, null); break; } - List packet = new(); - packet.Add((byte)windowId); // Window ID + List packet = new() + { + (byte)windowId // Window ID + }; // 1.18+ if (protocolVersion >= MC_1_18_1_Version) @@ -2829,7 +2837,7 @@ namespace MinecraftClient.Protocol.Handlers { try { - List packet = new List(); + List packet = new(); packet.AddRange(dataTypes.GetShort((short)slot)); packet.AddRange(dataTypes.GetItemSlot(new Item(itemType, count, nbt), itemPalette)); SendPacket(PacketTypesOut.CreativeInventoryAction, packet); @@ -2846,7 +2854,7 @@ namespace MinecraftClient.Protocol.Handlers { if (animation == 0 || animation == 1) { - List packet = new List(); + List packet = new(); if (protocolVersion < MC_1_8_Version) { @@ -2897,15 +2905,15 @@ namespace MinecraftClient.Protocol.Handlers try { if (line1.Length > 23) - line1 = line1.Substring(0, 23); + line1 = line1[..23]; if (line2.Length > 23) - line2 = line1.Substring(0, 23); + line2 = line1[..23]; if (line3.Length > 23) - line3 = line1.Substring(0, 23); + line3 = line1[..23]; if (line4.Length > 23) - line4 = line1.Substring(0, 23); + line4 = line1[..23]; - List packet = new List(); + List packet = new(); packet.AddRange(dataTypes.GetLocation(sign)); packet.AddRange(dataTypes.GetString(line1)); packet.AddRange(dataTypes.GetString(line2)); @@ -2925,7 +2933,7 @@ namespace MinecraftClient.Protocol.Handlers { try { - List packet = new List(); + List packet = new(); packet.AddRange(dataTypes.GetLocation(location)); packet.AddRange(dataTypes.GetString(command)); packet.AddRange(dataTypes.GetVarInt((int)mode)); @@ -2944,7 +2952,7 @@ namespace MinecraftClient.Protocol.Handlers { try { - List packet = new List(); + List packet = new(); packet.Add(windowID); packet.AddRange(dataTypes.GetShort(actionID)); packet.Add(accepted ? (byte)1 : (byte)0); @@ -2963,7 +2971,7 @@ namespace MinecraftClient.Protocol.Handlers { try { - List packet = new List(); + List packet = new(); packet.AddRange(dataTypes.GetVarInt(selectedSlot)); SendPacket(PacketTypesOut.SelectTrade, packet); return true; @@ -2982,7 +2990,7 @@ namespace MinecraftClient.Protocol.Handlers { try { - List packet = new List(); + List packet = new(); packet.AddRange(dataTypes.GetUUID(UUID)); SendPacket(PacketTypesOut.Spectate, packet); return true; diff --git a/MinecraftClient/Protocol/Handlers/Protocol18Forge.cs b/MinecraftClient/Protocol/Handlers/Protocol18Forge.cs index f3aa5634..d1be9b34 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18Forge.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18Forge.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using MinecraftClient.Protocol.Handlers.Forge; using System.Threading; +using MinecraftClient.Protocol.Handlers.Forge; namespace MinecraftClient.Protocol.Handlers { @@ -12,12 +12,12 @@ namespace MinecraftClient.Protocol.Handlers /// class Protocol18Forge { - private int protocolversion; - private DataTypes dataTypes; - private Protocol18Handler protocol18; - private IMinecraftComHandler mcHandler; + private readonly int protocolversion; + private readonly DataTypes dataTypes; + private readonly Protocol18Handler protocol18; + private readonly IMinecraftComHandler mcHandler; - private ForgeInfo forgeInfo; + private readonly ForgeInfo? forgeInfo; private FMLHandshakeClientState fmlHandshakeState = FMLHandshakeClientState.START; private bool ForgeEnabled() { return forgeInfo != null; } @@ -27,10 +27,10 @@ namespace MinecraftClient.Protocol.Handlers /// Forge Server Information /// Minecraft protocol version /// Minecraft data types handler - public Protocol18Forge(ForgeInfo forgeInfo, int protocolVersion, DataTypes dataTypes, Protocol18Handler protocol18, IMinecraftComHandler mcHandler) + public Protocol18Forge(ForgeInfo? forgeInfo, int protocolVersion, DataTypes dataTypes, Protocol18Handler protocol18, IMinecraftComHandler mcHandler) { this.forgeInfo = forgeInfo; - this.protocolversion = protocolVersion; + protocolversion = protocolVersion; this.dataTypes = dataTypes; this.protocol18 = protocol18; this.mcHandler = mcHandler; @@ -44,7 +44,7 @@ namespace MinecraftClient.Protocol.Handlers public string GetServerAddress(string serverAddress) { if (ForgeEnabled()) - return serverAddress + "\0" + forgeInfo.Version + "\0"; + return serverAddress + "\0" + forgeInfo!.Version + "\0"; return serverAddress; } @@ -54,7 +54,7 @@ namespace MinecraftClient.Protocol.Handlers /// Whether the handshake was successful. public bool CompleteForgeHandshake() { - if (ForgeEnabled() && forgeInfo.Version == FMLVersion.FML) + if (ForgeEnabled() && forgeInfo!.Version == FMLVersion.FML) { while (fmlHandshakeState != FMLHandshakeClientState.DONE) { @@ -103,7 +103,7 @@ namespace MinecraftClient.Protocol.Handlers /// TRUE if the plugin message was recognized and handled public bool HandlePluginMessage(string channel, Queue packetData, ref int currentDimension) { - if (ForgeEnabled() && forgeInfo.Version == FMLVersion.FML && fmlHandshakeState != FMLHandshakeClientState.DONE) + if (ForgeEnabled() && forgeInfo!.Version == FMLVersion.FML && fmlHandshakeState != FMLHandshakeClientState.DONE) { if (channel == "FML|HS") { @@ -239,7 +239,7 @@ namespace MinecraftClient.Protocol.Handlers /// TRUE/FALSE depending on whether the packet was understood or not public bool HandleLoginPluginRequest(string channel, Queue packetData, ref List responseData) { - if (ForgeEnabled() && forgeInfo.Version == FMLVersion.FML2 && channel == "fml:loginwrapper") + if (ForgeEnabled() && forgeInfo!.Version == FMLVersion.FML2 && channel == "fml:loginwrapper") { // Forge Handshake handler source code used to implement the FML2 packets: // https://github.com/MinecraftForge/MinecraftForge/blob/master/src/main/java/net/minecraftforge/fml/network/FMLNetworkConstants.java @@ -283,7 +283,7 @@ namespace MinecraftClient.Protocol.Handlers if (fmlChannel == "fml:handshake") { bool fmlResponseReady = false; - List fmlResponsePacket = new List(); + List fmlResponsePacket = new(); switch (packetID) { @@ -303,17 +303,17 @@ namespace MinecraftClient.Protocol.Handlers if (Settings.DebugMessages) Translations.WriteLineFormatted("forge.fml2.mod"); - List mods = new List(); + List mods = new(); int modCount = dataTypes.ReadNextVarInt(packetData); for (int i = 0; i < modCount; i++) mods.Add(dataTypes.ReadNextString(packetData)); - Dictionary channels = new Dictionary(); + Dictionary channels = new(); int channelCount = dataTypes.ReadNextVarInt(packetData); for (int i = 0; i < channelCount; i++) channels.Add(dataTypes.ReadNextString(packetData), dataTypes.ReadNextString(packetData)); - List registries = new List(); + List registries = new(); int registryCount = dataTypes.ReadNextVarInt(packetData); for (int i = 0; i < registryCount; i++) registries.Add(dataTypes.ReadNextString(packetData)); diff --git a/MinecraftClient/Protocol/Handlers/Protocol18Terrain.cs b/MinecraftClient/Protocol/Handlers/Protocol18Terrain.cs index 151e4f70..d144f37b 100644 --- a/MinecraftClient/Protocol/Handlers/Protocol18Terrain.cs +++ b/MinecraftClient/Protocol/Handlers/Protocol18Terrain.cs @@ -3,8 +3,6 @@ using System.Collections.Generic; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; //using System.Linq; //using System.Text; using MinecraftClient.Mapping; @@ -16,9 +14,9 @@ namespace MinecraftClient.Protocol.Handlers /// class Protocol18Terrain { - private int protocolversion; - private DataTypes dataTypes; - private IMinecraftComHandler handler; + private readonly int protocolversion; + private readonly DataTypes dataTypes; + private readonly IMinecraftComHandler handler; /// /// Initialize a new Terrain Decoder @@ -27,7 +25,7 @@ namespace MinecraftClient.Protocol.Handlers /// Minecraft Protocol Data Types public Protocol18Terrain(int protocolVersion, DataTypes dataTypes, IMinecraftComHandler handler) { - this.protocolversion = protocolVersion; + protocolversion = protocolVersion; this.dataTypes = dataTypes; this.handler = handler; } @@ -179,7 +177,7 @@ namespace MinecraftClient.Protocol.Handlers // 1.18 and above always contains all chunk section in data // 1.17 and 1.17.1 need vertical strip bitmask to know if the chunk section is included - if ((protocolversion >= Protocol18Handler.MC_1_18_1_Version) || + if ((protocolversion >= Protocol18Handler.MC_1_18_1_Version) || ((verticalStripBitmask![chunkY / 64] & (1UL << (chunkY % 64))) != 0)) { // Non-air block count inside chunk section, for lighting purposes @@ -277,7 +275,7 @@ namespace MinecraftClient.Protocol.Handlers // Block IDs are packed in the array of 64-bits integers ulong[] dataArray = dataTypes.ReadNextULongArray(cache); - Chunk chunk = new Chunk(); + Chunk chunk = new(); if (dataArray.Length > 0) { @@ -399,10 +397,10 @@ namespace MinecraftClient.Protocol.Handlers { if ((chunkMask & (1 << chunkY)) != 0) { - Chunk chunk = new Chunk(); + Chunk chunk = new(); //Read chunk data, all at once for performance reasons, and build the chunk object - Queue queue = new Queue(dataTypes.ReadNextUShortsLittleEndian(Chunk.SizeX * Chunk.SizeY * Chunk.SizeZ, cache)); + Queue queue = new(dataTypes.ReadNextUShortsLittleEndian(Chunk.SizeX * Chunk.SizeY * Chunk.SizeZ, cache)); for (int blockY = 0; blockY < Chunk.SizeY; blockY++) for (int blockZ = 0; blockZ < Chunk.SizeZ; blockZ++) for (int blockX = 0; blockX < Chunk.SizeX; blockX++) @@ -457,8 +455,8 @@ namespace MinecraftClient.Protocol.Handlers } //Read chunk data, unpacking 4-bit values into 8-bit values for block metadata - Queue blockTypes = new Queue(dataTypes.ReadData(Chunk.SizeX * Chunk.SizeY * Chunk.SizeZ * sectionCount, cache)); - Queue blockMeta = new Queue(); + Queue blockTypes = new(dataTypes.ReadData(Chunk.SizeX * Chunk.SizeY * Chunk.SizeZ * sectionCount, cache)); + Queue blockMeta = new(); foreach (byte packed in dataTypes.ReadData((Chunk.SizeX * Chunk.SizeY * Chunk.SizeZ * sectionCount) / 2, cache)) { byte hig = (byte)(packed >> 4); @@ -481,7 +479,7 @@ namespace MinecraftClient.Protocol.Handlers { if ((chunkMask & (1 << chunkY)) != 0) { - Chunk chunk = new Chunk(); + Chunk chunk = new(); for (int blockY = 0; blockY < Chunk.SizeY; blockY++) for (int blockZ = 0; blockZ < Chunk.SizeZ; blockZ++) diff --git a/MinecraftClient/Protocol/Handlers/SocketWrapper.cs b/MinecraftClient/Protocol/Handlers/SocketWrapper.cs index 084b6cf0..d9793024 100644 --- a/MinecraftClient/Protocol/Handlers/SocketWrapper.cs +++ b/MinecraftClient/Protocol/Handlers/SocketWrapper.cs @@ -9,8 +9,8 @@ namespace MinecraftClient.Protocol.Handlers /// class SocketWrapper { - TcpClient c; - AesCfb8Stream s; + readonly TcpClient c; + AesCfb8Stream? s; bool encrypted = false; /// @@ -19,7 +19,7 @@ namespace MinecraftClient.Protocol.Handlers /// TcpClient connected to the server public SocketWrapper(TcpClient client) { - this.c = client; + c = client; } /// @@ -49,8 +49,8 @@ namespace MinecraftClient.Protocol.Handlers { if (encrypted) throw new InvalidOperationException("Stream is already encrypted!?"); - this.s = new AesCfb8Stream(c.GetStream(), secretKey); - this.encrypted = true; + s = new AesCfb8Stream(c.GetStream(), secretKey); + encrypted = true; } /// @@ -62,10 +62,9 @@ namespace MinecraftClient.Protocol.Handlers while (read < offset) { if (encrypted) - { - read += s.Read(buffer, start + read, offset - read); - } - else read += c.Client.Receive(buffer, start + read, offset - read, f); + read += s!.Read(buffer, start + read, offset - read); + else + read += c.Client.Receive(buffer, start + read, offset - read, f); } } @@ -92,10 +91,9 @@ namespace MinecraftClient.Protocol.Handlers public void SendDataRAW(byte[] buffer) { if (encrypted) - { - s.Write(buffer, 0, buffer.Length); - } - else c.Client.Send(buffer); + s!.Write(buffer, 0, buffer.Length); + else + c.Client.Send(buffer); } /// diff --git a/MinecraftClient/Protocol/Handlers/ZlibUtils.cs b/MinecraftClient/Protocol/Handlers/ZlibUtils.cs index e7936b50..62f8bf85 100644 --- a/MinecraftClient/Protocol/Handlers/ZlibUtils.cs +++ b/MinecraftClient/Protocol/Handlers/ZlibUtils.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; -using Ionic.Zlib; +using Ionic.Zlib; namespace MinecraftClient.Protocol.Handlers { @@ -23,9 +18,9 @@ namespace MinecraftClient.Protocol.Handlers public static byte[] Compress(byte[] to_compress) { byte[] data; - using (System.IO.MemoryStream memstream = new System.IO.MemoryStream()) + using (System.IO.MemoryStream memstream = new()) { - using (ZlibStream stream = new ZlibStream(memstream, CompressionMode.Compress)) + using (ZlibStream stream = new(memstream, CompressionMode.Compress)) { stream.Write(to_compress, 0, to_compress.Length); } @@ -42,7 +37,7 @@ namespace MinecraftClient.Protocol.Handlers /// Decompressed data as a byte array public static byte[] Decompress(byte[] to_decompress, int size_uncompressed) { - ZlibStream stream = new ZlibStream(new System.IO.MemoryStream(to_decompress, false), CompressionMode.Decompress); + ZlibStream stream = new(new System.IO.MemoryStream(to_decompress, false), CompressionMode.Decompress); byte[] packetData_decompressed = new byte[size_uncompressed]; stream.Read(packetData_decompressed, 0, size_uncompressed); stream.Close(); @@ -56,15 +51,13 @@ namespace MinecraftClient.Protocol.Handlers /// Decompressed data as byte array public static byte[] Decompress(byte[] to_decompress) { - ZlibStream stream = new ZlibStream(new System.IO.MemoryStream(to_decompress, false), CompressionMode.Decompress); + ZlibStream stream = new(new System.IO.MemoryStream(to_decompress, false), CompressionMode.Decompress); byte[] buffer = new byte[16 * 1024]; - using (System.IO.MemoryStream decompressedBuffer = new System.IO.MemoryStream()) - { - int read; - while ((read = stream.Read(buffer, 0, buffer.Length)) > 0) - decompressedBuffer.Write(buffer, 0, read); - return decompressedBuffer.ToArray(); - } + using System.IO.MemoryStream decompressedBuffer = new(); + int read; + while ((read = stream.Read(buffer, 0, buffer.Length)) > 0) + decompressedBuffer.Write(buffer, 0, read); + return decompressedBuffer.ToArray(); } } } diff --git a/MinecraftClient/Protocol/IMinecraftCom.cs b/MinecraftClient/Protocol/IMinecraftCom.cs index d584d13b..a78383ff 100644 --- a/MinecraftClient/Protocol/IMinecraftCom.cs +++ b/MinecraftClient/Protocol/IMinecraftCom.cs @@ -1,10 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using MinecraftClient.Crypto; -using MinecraftClient.Mapping; using MinecraftClient.Inventory; +using MinecraftClient.Mapping; using MinecraftClient.Protocol.Keys; namespace MinecraftClient.Protocol diff --git a/MinecraftClient/Protocol/IMinecraftComHandler.cs b/MinecraftClient/Protocol/IMinecraftComHandler.cs index 6482b160..11040bfa 100644 --- a/MinecraftClient/Protocol/IMinecraftComHandler.cs +++ b/MinecraftClient/Protocol/IMinecraftComHandler.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using MinecraftClient.Mapping; using MinecraftClient.Inventory; using MinecraftClient.Logger; +using MinecraftClient.Mapping; using MinecraftClient.Protocol.Message; namespace MinecraftClient.Protocol @@ -223,7 +221,7 @@ namespace MinecraftClient.Protocol /// Entity id /// Equipment slot. 0: main hand, 1: off hand, 2–5: armor slot (2: boots, 3: leggings, 4: chestplate, 5: helmet)/param> /// Item/param> - void OnEntityEquipment(int entityid, int slot, Item item); + void OnEntityEquipment(int entityid, int slot, Item? item); /// /// Called when a player spawns or enters the client's render distance @@ -297,7 +295,7 @@ namespace MinecraftClient.Protocol /// Slot ID /// Item (may be null for empty slot) /// State ID - void OnSetSlot(byte inventoryID, short slotID, Item item, int stateId); + void OnSetSlot(byte inventoryID, short slotID, Item? item, int stateId); /// /// Called when player health or hunger changed. diff --git a/MinecraftClient/Protocol/JwtPayloadDecode.cs b/MinecraftClient/Protocol/JwtPayloadDecode.cs index b3626ee8..a103a4b8 100644 --- a/MinecraftClient/Protocol/JwtPayloadDecode.cs +++ b/MinecraftClient/Protocol/JwtPayloadDecode.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Text; namespace MinecraftClient.Protocol @@ -25,7 +23,7 @@ namespace MinecraftClient.Protocol case 0: break; // No pad chars in this case case 2: output += "=="; break; // Two pad chars case 3: output += "="; break; // One pad char - default: throw new System.ArgumentOutOfRangeException("input", "Illegal base64url string!"); + default: throw new System.ArgumentOutOfRangeException(nameof(input), "Illegal base64url string!"); } var converted = Convert.FromBase64String(output); // Standard base64 decoder return converted; diff --git a/MinecraftClient/Protocol/Message/ChatMessage.cs b/MinecraftClient/Protocol/Message/ChatMessage.cs index 28d4c650..790c70af 100644 --- a/MinecraftClient/Protocol/Message/ChatMessage.cs +++ b/MinecraftClient/Protocol/Message/ChatMessage.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace MinecraftClient.Protocol.Message { @@ -41,7 +37,7 @@ namespace MinecraftClient.Protocol.Message isSystemChat = false; this.content = content; this.isJson = isJson; - this.chatTypeId = chatType; + chatTypeId = chatType; this.senderUUID = senderUUID; this.unsignedContent = unsignedContent; this.displayName = displayName; @@ -57,18 +53,18 @@ namespace MinecraftClient.Protocol.Message this.isSystemChat = isSystemChat; this.content = content; this.isJson = isJson; - this.chatTypeId = chatType; + chatTypeId = chatType; this.senderUUID = senderUUID; } - public LastSeenMessageList.Entry? toLastSeenMessageEntry() + public LastSeenMessageList.Entry? ToLastSeenMessageEntry() { return signature != null ? new LastSeenMessageList.Entry(senderUUID, signature) : null; } - public bool lacksSender() + public bool LacksSender() { - return this.senderUUID == Guid.Empty; + return senderUUID == Guid.Empty; } } } diff --git a/MinecraftClient/Protocol/Message/ChatParser.cs b/MinecraftClient/Protocol/Message/ChatParser.cs index 650a005d..b47c4e08 100644 --- a/MinecraftClient/Protocol/Message/ChatParser.cs +++ b/MinecraftClient/Protocol/Message/ChatParser.cs @@ -1,8 +1,9 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; +using System.Net.Http; using System.Text; +using System.Threading.Tasks; using MinecraftClient.Protocol.Message; namespace MinecraftClient.Protocol @@ -140,27 +141,31 @@ namespace MinecraftClient.Protocol /// Color code private static string Color2tag(string colorname) { - switch (colorname.ToLower()) + return colorname.ToLower() switch { - /* MC 1.7+ Name MC 1.6 Name Classic tag */ - case "black": /* Blank if same */ return "§0"; - case "dark_blue": return "§1"; - case "dark_green": return "§2"; - case "dark_aqua": case "dark_cyan": return "§3"; - case "dark_red": return "§4"; - case "dark_purple": case "dark_magenta": return "§5"; - case "gold": case "dark_yellow": return "§6"; - case "gray": return "§7"; - case "dark_gray": return "§8"; - case "blue": return "§9"; - case "green": return "§a"; - case "aqua": case "cyan": return "§b"; - case "red": return "§c"; - case "light_purple": case "magenta": return "§d"; - case "yellow": return "§e"; - case "white": return "§f"; - default: return ""; - } +#pragma warning disable format // @formatter:off + + /* MC 1.7+ Name || MC 1.6 Name || Classic tag */ + "black" => "§0", + "dark_blue" => "§1", + "dark_green" => "§2", + "dark_aqua" or "dark_cyan" => "§3", + "dark_red" => "§4", + "dark_purple" or "dark_magenta" => "§5", + "gold" or "dark_yellow" => "§6", + "gray" => "§7", + "dark_gray" => "§8", + "blue" => "§9", + "green" => "§a", + "aqua" or "cyan" => "§b", + "red" => "§c", + "light_purple" or "magenta" => "§d", + "yellow" => "§e", + "white" => "§f", + _ => "" , + +#pragma warning restore format // @formatter:on + }; } /// @@ -171,7 +176,7 @@ namespace MinecraftClient.Protocol /// /// Set of translation rules for formatting text /// - private static Dictionary TranslationRules = new Dictionary(); + private static readonly Dictionary TranslationRules = new(); /// /// Initialize translation rules. @@ -204,29 +209,38 @@ namespace MinecraftClient.Protocol if (!File.Exists(Language_File)) { ConsoleIO.WriteLineFormatted(Translations.Get("chat.download", Settings.Language)); + HttpClient httpClient = new(); try { - string assets_index = DownloadString(Settings.TranslationsFile_Website_Index); + Task fetch_index = httpClient.GetStringAsync(Settings.TranslationsFile_Website_Index); + fetch_index.Wait(); + string assets_index = fetch_index.Result; + fetch_index.Dispose(); + string[] tmp = assets_index.Split(new string[] { "minecraft/lang/" + Settings.Language.ToLower() + ".json" }, StringSplitOptions.None); tmp = tmp[1].Split(new string[] { "hash\": \"" }, StringSplitOptions.None); string hash = tmp[1].Split('"')[0]; //Translations file identifier on Mojang's servers - string translation_file_location = Settings.TranslationsFile_Website_Download + '/' + hash.Substring(0, 2) + '/' + hash; + string translation_file_location = Settings.TranslationsFile_Website_Download + '/' + hash[..2] + '/' + hash; if (Settings.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("chat.request", translation_file_location)); - StringBuilder stringBuilder = new StringBuilder(); - foreach (KeyValuePair entry in Json.ParseJson(DownloadString(translation_file_location)).Properties) - { - stringBuilder.Append(entry.Key + "=" + entry.Value.StringValue + Environment.NewLine); - } + Task fetch_file = httpClient.GetStringAsync(translation_file_location); + fetch_file.Wait(); + string translation_file = fetch_file.Result; + fetch_file.Dispose(); + StringBuilder stringBuilder = new(); + foreach (KeyValuePair entry in Json.ParseJson(translation_file).Properties) + stringBuilder.Append(entry.Key).Append('=').Append(entry.Value.StringValue).Append(Environment.NewLine); File.WriteAllText(Language_File, stringBuilder.ToString()); + ConsoleIO.WriteLineFormatted(Translations.Get("chat.done", Language_File)); } catch { Translations.WriteLineFormatted("chat.fail"); } + httpClient.Dispose(); } //Download Failed? Defaulting to en_GB.lang if the game is installed @@ -275,7 +289,7 @@ namespace MinecraftClient.Protocol { int using_idx = 0; string rule = TranslationRules[rulename]; - StringBuilder result = new StringBuilder(); + StringBuilder result = new(); for (int i = 0; i < rule.Length; i++) { if (rule[i] == '%' && i + 1 < rule.Length) @@ -354,7 +368,7 @@ namespace MinecraftClient.Protocol } else if (data.Properties.ContainsKey("translate")) { - List using_data = new List(); + List using_data = new(); if (data.Properties.ContainsKey("using") && !data.Properties.ContainsKey("with")) data.Properties["with"] = data.Properties["using"]; if (data.Properties.ContainsKey("with")) @@ -383,22 +397,5 @@ namespace MinecraftClient.Protocol return ""; } - - /// - /// Do a HTTP request to get a webpage or text data from a server file - /// - /// URL of resource - /// Returns resource data if success, otherwise a WebException is raised - private static string DownloadString(string url) - { - System.Net.HttpWebRequest myRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url); - myRequest.Method = "GET"; - System.Net.WebResponse myResponse = myRequest.GetResponse(); - StreamReader sr = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8); - string result = sr.ReadToEnd(); - sr.Close(); - myResponse.Close(); - return result; - } } } diff --git a/MinecraftClient/Protocol/Message/LastSeenMessageList.cs b/MinecraftClient/Protocol/Message/LastSeenMessageList.cs index 262b1b55..c3de5178 100644 --- a/MinecraftClient/Protocol/Message/LastSeenMessageList.cs +++ b/MinecraftClient/Protocol/Message/LastSeenMessageList.cs @@ -1,8 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace MinecraftClient.Protocol.Message { @@ -11,7 +8,7 @@ namespace MinecraftClient.Protocol.Message /// public class LastSeenMessageList { - public static readonly LastSeenMessageList EMPTY = new(new Entry[0]); + public static readonly LastSeenMessageList EMPTY = new(Array.Empty()); public static readonly int MAX_ENTRIES = 5; public Entry[] entries; @@ -103,7 +100,7 @@ namespace MinecraftClient.Protocol.Message entries[size++] = lastEntry; LastSeenMessageList.Entry[] msgList = new LastSeenMessageList.Entry[size]; - for (int i = 0; i < size; ++i) + for (int i = 0; i < size; ++i) msgList[i] = entries[i]; lastSeenMessages = new LastSeenMessageList(msgList); } diff --git a/MinecraftClient/Protocol/MicrosoftAuthentication.cs b/MinecraftClient/Protocol/MicrosoftAuthentication.cs index b419806c..15cd710e 100644 --- a/MinecraftClient/Protocol/MicrosoftAuthentication.cs +++ b/MinecraftClient/Protocol/MicrosoftAuthentication.cs @@ -1,11 +1,10 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; using System.Collections.Specialized; using System.Diagnostics; +using System.Linq; using System.Runtime.InteropServices; +using System.Text.RegularExpressions; namespace MinecraftClient.Protocol { @@ -58,8 +57,10 @@ namespace MinecraftClient.Protocol /// private static LoginResponse RequestToken(string postData) { - var request = new ProxiedWebRequest(tokenUrl); - request.UserAgent = "MCC/" + Program.Version; + var request = new ProxiedWebRequest(tokenUrl) + { + UserAgent = "MCC/" + Program.Version + }; var response = request.Post("application/x-www-form-urlencoded", postData); var jsonData = Json.ParseJson(response.Body); @@ -132,17 +133,17 @@ namespace MinecraftClient.Protocol static class XboxLive { - private static string authorize = "https://login.live.com/oauth20_authorize.srf?client_id=000000004C12AE6F&redirect_uri=https://login.live.com/oauth20_desktop.srf&scope=service::user.auth.xboxlive.com::MBI_SSL&display=touch&response_type=token&locale=en"; - private static string xbl = "https://user.auth.xboxlive.com/user/authenticate"; - private static string xsts = "https://xsts.auth.xboxlive.com/xsts/authorize"; + private static readonly string authorize = "https://login.live.com/oauth20_authorize.srf?client_id=000000004C12AE6F&redirect_uri=https://login.live.com/oauth20_desktop.srf&scope=service::user.auth.xboxlive.com::MBI_SSL&display=touch&response_type=token&locale=en"; + private static readonly string xbl = "https://user.auth.xboxlive.com/user/authenticate"; + private static readonly string xsts = "https://xsts.auth.xboxlive.com/xsts/authorize"; - private static string userAgent = "Mozilla/5.0 (XboxReplay; XboxLiveAuth/3.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"; + private static readonly string userAgent = "Mozilla/5.0 (XboxReplay; XboxLiveAuth/3.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"; - private static Regex ppft = new Regex("sFTTag:'.*value=\"(.*)\"\\/>'"); - private static Regex urlPost = new Regex("urlPost:'(.+?(?=\'))"); - private static Regex confirm = new Regex("identity\\/confirm"); - private static Regex invalidAccount = new Regex("Sign in to", RegexOptions.IgnoreCase); - private static Regex twoFA = new Regex("Help us protect your account", RegexOptions.IgnoreCase); + private static readonly Regex ppft = new("sFTTag:'.*value=\"(.*)\"\\/>'"); + private static readonly Regex urlPost = new("urlPost:'(.+?(?=\'))"); + private static readonly Regex confirm = new("identity\\/confirm"); + private static readonly Regex invalidAccount = new("Sign in to", RegexOptions.IgnoreCase); + private static readonly Regex twoFA = new("Help us protect your account", RegexOptions.IgnoreCase); public static string SignInUrl { get { return authorize; } } @@ -153,8 +154,10 @@ namespace MinecraftClient.Protocol /// public static PreAuthResponse PreAuth() { - var request = new ProxiedWebRequest(authorize); - request.UserAgent = userAgent; + var request = new ProxiedWebRequest(authorize) + { + UserAgent = userAgent + }; var response = request.Get(); string html = response.Body; @@ -188,8 +191,10 @@ namespace MinecraftClient.Protocol /// public static Microsoft.LoginResponse UserLogin(string email, string password, PreAuthResponse preAuth) { - var request = new ProxiedWebRequest(preAuth.UrlPost, preAuth.Cookie); - request.UserAgent = userAgent; + var request = new ProxiedWebRequest(preAuth.UrlPost, preAuth.Cookie) + { + UserAgent = userAgent + }; string postData = "login=" + Uri.EscapeDataString(email) + "&loginfmt=" + Uri.EscapeDataString(email) @@ -205,7 +210,7 @@ namespace MinecraftClient.Protocol if (response.StatusCode >= 300 && response.StatusCode <= 399) { - string url = response.Headers.Get("Location"); + string url = response.Headers.Get("Location")!; string hash = url.Split('#')[1]; var request2 = new ProxiedWebRequest(url); @@ -257,9 +262,11 @@ namespace MinecraftClient.Protocol /// public static XblAuthenticateResponse XblAuthenticate(Microsoft.LoginResponse loginResponse) { - var request = new ProxiedWebRequest(xbl); - request.UserAgent = userAgent; - request.Accept = "application/json"; + var request = new ProxiedWebRequest(xbl) + { + UserAgent = userAgent, + Accept = "application/json" + }; request.Headers.Add("x-xbl-contract-version", "0"); var accessToken = loginResponse.AccessToken; @@ -312,9 +319,11 @@ namespace MinecraftClient.Protocol /// public static XSTSAuthenticateResponse XSTSAuthenticate(XblAuthenticateResponse xblResponse) { - var request = new ProxiedWebRequest(xsts); - request.UserAgent = userAgent; - request.Accept = "application/json"; + var request = new ProxiedWebRequest(xsts) + { + UserAgent = userAgent, + Accept = "application/json" + }; request.Headers.Add("x-xbl-contract-version", "1"); string payload = "{" @@ -388,9 +397,9 @@ namespace MinecraftClient.Protocol static class MinecraftWithXbox { - private static string loginWithXbox = "https://api.minecraftservices.com/authentication/login_with_xbox"; - private static string ownership = "https://api.minecraftservices.com/entitlements/mcstore"; - private static string profile = "https://api.minecraftservices.com/minecraft/profile"; + private static readonly string loginWithXbox = "https://api.minecraftservices.com/authentication/login_with_xbox"; + private static readonly string ownership = "https://api.minecraftservices.com/entitlements/mcstore"; + private static readonly string profile = "https://api.minecraftservices.com/minecraft/profile"; /// /// Login to Minecraft using the XSTS token and user hash obtained before @@ -400,8 +409,10 @@ namespace MinecraftClient.Protocol /// public static string LoginWithXbox(string userHash, string xstsToken) { - var request = new ProxiedWebRequest(loginWithXbox); - request.Accept = "application/json"; + var request = new ProxiedWebRequest(loginWithXbox) + { + Accept = "application/json" + }; string payload = "{\"identityToken\": \"XBL3.0 x=" + userHash + ";" + xstsToken + "\"}"; var response = request.Post("application/json", payload); diff --git a/MinecraftClient/Protocol/MojangAPI.cs b/MinecraftClient/Protocol/MojangAPI.cs index 78c8e7de..e0dade07 100644 --- a/MinecraftClient/Protocol/MojangAPI.cs +++ b/MinecraftClient/Protocol/MojangAPI.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; -using System.Net; +using System.Net.Http; +using System.Threading.Tasks; /// !!! ATTENTION !!! /// By using these functions you agree to the ToS of the Mojang API. @@ -72,7 +73,7 @@ namespace MinecraftClient.Protocol public static class MojangAPI { // Initialize webclient for all functions - private static readonly WebClient wc = new WebClient(); + private static readonly HttpClient httpClient = new(); // Can be removed in newer C# versions. // Replace with DateTimeOffset.FromUnixTimeMilliseconds() @@ -81,10 +82,10 @@ namespace MinecraftClient.Protocol /// /// A unix timestamp as double /// Datetime of unix timestamp - private static DateTime unixTimeStampToDateTime(double unixTimeStamp) + private static DateTime UnixTimeStampToDateTime(double unixTimeStamp) { // Unix timestamp is seconds past epoch - DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + DateTime dateTime = new(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); dateTime = dateTime.AddMilliseconds(unixTimeStamp).ToLocalTime(); return dateTime; } @@ -95,11 +96,10 @@ namespace MinecraftClient.Protocol /// /// string to convert /// ServiceStatus enum, red as default. - private static ServiceStatus stringToServiceStatus(string s) + private static ServiceStatus StringToServiceStatus(string s) { - ServiceStatus servStat; - if (Enum.TryParse(s, out servStat)) + if (Enum.TryParse(s, out ServiceStatus servStat)) { return servStat; } @@ -119,7 +119,11 @@ namespace MinecraftClient.Protocol { try { - return Json.ParseJson(wc.DownloadString("https://api.mojang.com/users/profiles/minecraft/" + name)).Properties["id"].StringValue; + Task fetchTask = httpClient.GetStringAsync("https://api.mojang.com/users/profiles/minecraft/" + name); + fetchTask.Wait(); + string result = Json.ParseJson(fetchTask.Result).Properties["id"].StringValue; + fetchTask.Dispose(); + return result; } catch (Exception) { return string.Empty; } } @@ -134,10 +138,13 @@ namespace MinecraftClient.Protocol // Perform web request try { - var nameChanges = Json.ParseJson(wc.DownloadString("https://api.mojang.com/user/profiles/" + uuid + "/names")).DataArray; + Task fetchTask = httpClient.GetStringAsync("https://api.mojang.com/user/profiles/" + uuid + "/names"); + fetchTask.Wait(); + var nameChanges = Json.ParseJson(fetchTask.Result).DataArray; + fetchTask.Dispose(); // Names are sorted from past to most recent. We need to get the last name in the list - return nameChanges[nameChanges.Count - 1].Properties["name"].StringValue; + return nameChanges[^1].Properties["name"].StringValue; } catch (Exception) { return string.Empty; } } @@ -149,13 +156,16 @@ namespace MinecraftClient.Protocol /// Name history, as a dictionary public static Dictionary UuidToNameHistory(string uuid) { - Dictionary tempDict = new Dictionary(); + Dictionary tempDict = new(); List jsonDataList; // Perform web request try { - jsonDataList = Json.ParseJson(wc.DownloadString("https://api.mojang.com/user/profiles/" + uuid + "/names")).DataArray; + Task fetchTask = httpClient.GetStringAsync("https://api.mojang.com/user/profiles/" + uuid + "/names"); + fetchTask.Wait(); + jsonDataList = Json.ParseJson(fetchTask.Result).DataArray; + fetchTask.Dispose(); } catch (Exception) { return tempDict; } @@ -171,7 +181,7 @@ namespace MinecraftClient.Protocol // // Workaround for converting Unix time to normal time. - DateTimeOffset creationDate = unixTimeStampToDateTime(Convert.ToDouble(jsonData.Properties["changedToAt"].StringValue)); + DateTimeOffset creationDate = UnixTimeStampToDateTime(Convert.ToDouble(jsonData.Properties["changedToAt"].StringValue)); // Add Keyvaluepair to dict. tempDict.Add(jsonData.Properties["name"].StringValue, creationDate.DateTime); @@ -193,24 +203,30 @@ namespace MinecraftClient.Protocol /// Dictionary of the Mojang services public static MojangServiceStatus GetMojangServiceStatus() { - List jsonDataList = new List(); + List jsonDataList; // Perform web request try { - jsonDataList = Json.ParseJson(wc.DownloadString("https://status.mojang.com/check")).DataArray; + Task fetchTask = httpClient.GetStringAsync("https://status.mojang.com/check"); + fetchTask.Wait(); + jsonDataList = Json.ParseJson(fetchTask.Result).DataArray; + fetchTask.Dispose(); + } + catch (Exception) + { + return new MojangServiceStatus(); } - catch (Exception) { new MojangServiceStatus(); } // Convert string to enum values and store them inside a MojangeServiceStatus object. - return new MojangServiceStatus(minecraftNet: stringToServiceStatus(jsonDataList[0].Properties["minecraft.net"].StringValue), - sessionMinecraftNet: stringToServiceStatus(jsonDataList[1].Properties["session.minecraft.net"].StringValue), - accountMojangCom: stringToServiceStatus(jsonDataList[2].Properties["account.mojang.com"].StringValue), - authserverMojangCom: stringToServiceStatus(jsonDataList[3].Properties["authserver.mojang.com"].StringValue), - sessionserverMojangCom: stringToServiceStatus(jsonDataList[4].Properties["sessionserver.mojang.com"].StringValue), - apiMojangCom: stringToServiceStatus(jsonDataList[5].Properties["api.mojang.com"].StringValue), - texturesMinecraftNet: stringToServiceStatus(jsonDataList[6].Properties["textures.minecraft.net"].StringValue), - mojangCom: stringToServiceStatus(jsonDataList[7].Properties["mojang.com"].StringValue) + return new MojangServiceStatus(minecraftNet: StringToServiceStatus(jsonDataList[0].Properties["minecraft.net"].StringValue), + sessionMinecraftNet: StringToServiceStatus(jsonDataList[1].Properties["session.minecraft.net"].StringValue), + accountMojangCom: StringToServiceStatus(jsonDataList[2].Properties["account.mojang.com"].StringValue), + authserverMojangCom: StringToServiceStatus(jsonDataList[3].Properties["authserver.mojang.com"].StringValue), + sessionserverMojangCom: StringToServiceStatus(jsonDataList[4].Properties["sessionserver.mojang.com"].StringValue), + apiMojangCom: StringToServiceStatus(jsonDataList[5].Properties["api.mojang.com"].StringValue), + texturesMinecraftNet: StringToServiceStatus(jsonDataList[6].Properties["textures.minecraft.net"].StringValue), + mojangCom: StringToServiceStatus(jsonDataList[7].Properties["mojang.com"].StringValue) ); } @@ -228,8 +244,11 @@ namespace MinecraftClient.Protocol // Perform web request try { + Task fetchTask = httpClient.GetStringAsync("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid); + fetchTask.Wait(); // Obtain the Base64 encoded skin information from the API. Discard the rest, since it can be obtained easier through other requests. - base64SkinInfo = Json.ParseJson(wc.DownloadString("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid)).Properties["properties"].DataArray[0].Properties["value"].StringValue; + base64SkinInfo = Json.ParseJson(fetchTask.Result).Properties["properties"].DataArray[0].Properties["value"].StringValue; + fetchTask.Dispose(); } catch (Exception) { return new SkinInfo(); } @@ -267,7 +286,7 @@ namespace MinecraftClient.Protocol /// True if the default model for this UUID is Alex public static bool DefaultModelAlex(string uuid) { - return hashCode(uuid) % 2 == 1; + return HashCode(uuid) % 2 == 1; } /// @@ -275,7 +294,7 @@ namespace MinecraftClient.Protocol /// /// UUID of a player. /// - private static int hashCode(string hash) + private static int HashCode(string hash) { byte[] data = GuidExtensions.ToLittleEndian(new Guid(hash)).ToByteArray(); diff --git a/MinecraftClient/Protocol/PlayerInfo.cs b/MinecraftClient/Protocol/PlayerInfo.cs index 3d6f0a40..b77aea58 100644 --- a/MinecraftClient/Protocol/PlayerInfo.cs +++ b/MinecraftClient/Protocol/PlayerInfo.cs @@ -1,8 +1,5 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using MinecraftClient.Protocol.Keys; using MinecraftClient.Protocol.Message; @@ -76,12 +73,12 @@ namespace MinecraftClient.Protocol public bool IsMessageChainLegal() { - return this.lastMessageVerified; + return lastMessageVerified; } public bool IsKeyExpired() { - return DateTime.Now.ToUniversalTime() > this.KeyExpiresAt; + return DateTime.Now.ToUniversalTime() > KeyExpiresAt; } /// @@ -119,16 +116,16 @@ namespace MinecraftClient.Protocol /// Is this message chain vaild public bool VerifyMessage(string message, long timestamp, long salt, ref byte[] signature, ref byte[]? precedingSignature, LastSeenMessageList lastSeenMessages) { - if (this.lastMessageVerified == false) + if (lastMessageVerified == false) return false; if (PublicKey == null || IsKeyExpired() || (this.precedingSignature != null && precedingSignature == null)) { - this.lastMessageVerified = false; + lastMessageVerified = false; return false; } if (this.precedingSignature != null && !this.precedingSignature.SequenceEqual(precedingSignature!)) { - this.lastMessageVerified = false; + lastMessageVerified = false; return false; } @@ -139,7 +136,7 @@ namespace MinecraftClient.Protocol bool res = PublicKey.VerifyMessage(message, Uuid, timeOffset, ref saltByte, ref signature, ref precedingSignature, lastSeenMessages); - this.lastMessageVerified = res; + lastMessageVerified = res; this.precedingSignature = signature; return res; @@ -154,22 +151,22 @@ namespace MinecraftClient.Protocol /// Is this message chain vaild public bool VerifyMessageHead(ref byte[]? precedingSignature, ref byte[] headerSignature, ref byte[] bodyDigest) { - if (this.lastMessageVerified == false) + if (lastMessageVerified == false) return false; if (PublicKey == null || IsKeyExpired() || (this.precedingSignature != null && precedingSignature == null)) { - this.lastMessageVerified = false; + lastMessageVerified = false; return false; } if (this.precedingSignature != null && !this.precedingSignature.SequenceEqual(precedingSignature!)) { - this.lastMessageVerified = false; + lastMessageVerified = false; return false; } bool res = PublicKey.VerifyHeader(Uuid, ref bodyDigest, ref headerSignature, ref precedingSignature); - this.lastMessageVerified = res; + lastMessageVerified = res; this.precedingSignature = headerSignature; return res; diff --git a/MinecraftClient/Protocol/ProfileKey/KeyUtils.cs b/MinecraftClient/Protocol/ProfileKey/KeyUtils.cs index 9bf348fb..9d8f4dfd 100644 --- a/MinecraftClient/Protocol/ProfileKey/KeyUtils.cs +++ b/MinecraftClient/Protocol/ProfileKey/KeyUtils.cs @@ -1,10 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Security.Cryptography; using System.Text; -using System.Threading.Tasks; -using MinecraftClient.Protocol.Handlers; using MinecraftClient.Protocol.Message; namespace MinecraftClient.Protocol.Keys diff --git a/MinecraftClient/Protocol/ProfileKey/KeysCache.cs b/MinecraftClient/Protocol/ProfileKey/KeysCache.cs index 0e492456..44998da4 100644 --- a/MinecraftClient/Protocol/ProfileKey/KeysCache.cs +++ b/MinecraftClient/Protocol/ProfileKey/KeysCache.cs @@ -14,11 +14,11 @@ namespace MinecraftClient.Protocol.Keys { private const string KeysCacheFilePlaintext = "ProfileKeyCache.ini"; - private static FileMonitor cachemonitor; - private static Dictionary keys = new Dictionary(); - private static Timer updatetimer = new Timer(100); - private static List> pendingadds = new List>(); - private static BinaryFormatter formatter = new BinaryFormatter(); + private static FileMonitor? cachemonitor; + private static readonly Dictionary keys = new(); + private static readonly Timer updatetimer = new(100); + private static readonly List> pendingadds = new(); + private static readonly BinaryFormatter formatter = new(); /// /// Retrieve whether KeysCache contains a keys for the given login. @@ -93,7 +93,7 @@ namespace MinecraftClient.Protocol.Keys /// /// Sender /// Event data - private static void HandlePending(object sender, ElapsedEventArgs e) + private static void HandlePending(object? sender, ElapsedEventArgs e) { updatetimer.Stop(); LoadFromDisk(); @@ -177,9 +177,11 @@ namespace MinecraftClient.Protocol.Keys if (Settings.DebugMessages) Translations.WriteLineFormatted("cache.saving_keys"); - List KeysCacheLines = new List(); - KeysCacheLines.Add("# Generated by MCC v" + Program.Version + " - Keep it secret & Edit at own risk!"); - KeysCacheLines.Add("# ProfileKey=PublicKey(base64),PublicKeySignature(base64),PublicKeySignatureV2(base64),PrivateKey(base64),ExpiresAt,RefreshAfter"); + List KeysCacheLines = new() + { + "# Generated by MCC v" + Program.Version + " - Keep it secret & Edit at own risk!", + "# ProfileKey=PublicKey(base64),PublicKeySignature(base64),PublicKeySignatureV2(base64),PrivateKey(base64),ExpiresAt,RefreshAfter" + }; foreach (KeyValuePair entry in keys) KeysCacheLines.Add(entry.Key + '=' + entry.Value.ToString()); diff --git a/MinecraftClient/Protocol/ProfileKey/PlayerKeyPair.cs b/MinecraftClient/Protocol/ProfileKey/PlayerKeyPair.cs index 8f85e382..d7b0fe39 100644 --- a/MinecraftClient/Protocol/ProfileKey/PlayerKeyPair.cs +++ b/MinecraftClient/Protocol/ProfileKey/PlayerKeyPair.cs @@ -34,12 +34,12 @@ namespace MinecraftClient.Protocol.Keys public bool NeedRefresh() { - return DateTime.Now.ToUniversalTime() > this.RefreshedAfter; + return DateTime.Now.ToUniversalTime() > RefreshedAfter; } public bool IsExpired() { - return DateTime.Now.ToUniversalTime() > this.ExpiresAt; + return DateTime.Now.ToUniversalTime() > ExpiresAt; } public long GetExpirationMilliseconds() @@ -61,17 +61,17 @@ namespace MinecraftClient.Protocol.Keys if (fields.Length < 6) throw new InvalidDataException("Invalid string format"); - PublicKey publicKey = new PublicKey(pemKey: fields[0].Trim(), + PublicKey publicKey = new(pemKey: fields[0].Trim(), sig: fields[1].Trim(), sigV2: fields[2].Trim()); - PrivateKey privateKey = new PrivateKey(pemKey: fields[3].Trim()); + PrivateKey privateKey = new(pemKey: fields[3].Trim()); return new PlayerKeyPair(publicKey, privateKey, fields[4].Trim(), fields[5].Trim()); } public override string ToString() { - List datas = new List(); + List datas = new(); datas.Add(Convert.ToBase64String(PublicKey.Key)); if (PublicKey.Signature == null) datas.Add(String.Empty); diff --git a/MinecraftClient/Protocol/ProfileKey/PrivateKey.cs b/MinecraftClient/Protocol/ProfileKey/PrivateKey.cs index 0683ef46..b3dd4093 100644 --- a/MinecraftClient/Protocol/ProfileKey/PrivateKey.cs +++ b/MinecraftClient/Protocol/ProfileKey/PrivateKey.cs @@ -1,9 +1,5 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Security.Cryptography; -using System.Text; -using System.Threading.Tasks; using MinecraftClient.Protocol.Message; namespace MinecraftClient.Protocol.Keys @@ -18,10 +14,10 @@ namespace MinecraftClient.Protocol.Keys public PrivateKey(string pemKey) { - this.Key = KeyUtils.DecodePemKey(pemKey, "-----BEGIN RSA PRIVATE KEY-----", "-----END RSA PRIVATE KEY-----"); + Key = KeyUtils.DecodePemKey(pemKey, "-----BEGIN RSA PRIVATE KEY-----", "-----END RSA PRIVATE KEY-----"); - this.rsa = RSA.Create(); - rsa.ImportPkcs8PrivateKey(this.Key, out _); + rsa = RSA.Create(); + rsa.ImportPkcs8PrivateKey(Key, out _); } public byte[] SignData(byte[] data) @@ -62,8 +58,8 @@ namespace MinecraftClient.Protocol.Keys byte[] msgSignData = KeyUtils.GetSignatureData(precedingSignature, uuid, bodyDigest); byte[] msgSign = SignData(msgSignData); - - this.precedingSignature = msgSign; + + precedingSignature = msgSign; return msgSign; } diff --git a/MinecraftClient/Protocol/ProfileKey/PublicKey.cs b/MinecraftClient/Protocol/ProfileKey/PublicKey.cs index 8ceb55e1..429c3962 100644 --- a/MinecraftClient/Protocol/ProfileKey/PublicKey.cs +++ b/MinecraftClient/Protocol/ProfileKey/PublicKey.cs @@ -1,9 +1,5 @@ using System; -using System.Collections.Generic; -using System.Linq; using System.Security.Cryptography; -using System.Text; -using System.Threading.Tasks; using MinecraftClient.Protocol.Message; namespace MinecraftClient.Protocol.Keys @@ -18,26 +14,26 @@ namespace MinecraftClient.Protocol.Keys public PublicKey(string pemKey, string? sig = null, string? sigV2 = null) { - this.Key = KeyUtils.DecodePemKey(pemKey, "-----BEGIN RSA PUBLIC KEY-----", "-----END RSA PUBLIC KEY-----"); + Key = KeyUtils.DecodePemKey(pemKey, "-----BEGIN RSA PUBLIC KEY-----", "-----END RSA PUBLIC KEY-----"); - this.rsa = RSA.Create(); - rsa.ImportSubjectPublicKeyInfo(this.Key, out _); + rsa = RSA.Create(); + rsa.ImportSubjectPublicKeyInfo(Key, out _); if (!string.IsNullOrEmpty(sig)) - this.Signature = Convert.FromBase64String(sig); + Signature = Convert.FromBase64String(sig); if (!string.IsNullOrEmpty(sigV2)) - this.SignatureV2 = Convert.FromBase64String(sigV2!); + SignatureV2 = Convert.FromBase64String(sigV2!); } public PublicKey(byte[] key, byte[] signature) { - this.Key = key; + Key = key; - this.rsa = RSA.Create(); - rsa.ImportSubjectPublicKeyInfo(this.Key, out _); + rsa = RSA.Create(); + rsa.ImportSubjectPublicKeyInfo(Key, out _); - this.Signature = signature; + Signature = signature; } public bool VerifyData(byte[] data, byte[] signature) diff --git a/MinecraftClient/Protocol/ProtocolHandler.cs b/MinecraftClient/Protocol/ProtocolHandler.cs index eaa449fa..4fb1b190 100644 --- a/MinecraftClient/Protocol/ProtocolHandler.cs +++ b/MinecraftClient/Protocol/ProtocolHandler.cs @@ -1,16 +1,15 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Net.Sockets; using System.Net.Security; -using System.Threading; +using System.Net.Sockets; +using System.Security.Authentication; +using System.Text; using DnsClient; -using MinecraftClient.Proxy; using MinecraftClient.Protocol.Handlers; using MinecraftClient.Protocol.Handlers.Forge; using MinecraftClient.Protocol.Session; -using System.Security.Authentication; +using MinecraftClient.Proxy; namespace MinecraftClient.Protocol { @@ -88,8 +87,8 @@ namespace MinecraftClient.Protocol { try { - if (Protocol18Handler.doPing(serverIP, serverPort, ref protocolversionTmp, ref forgeInfoTmp) - || Protocol16Handler.doPing(serverIP, serverPort, ref protocolversionTmp)) + if (Protocol18Handler.DoPing(serverIP, serverPort, ref protocolversionTmp, ref forgeInfoTmp) + || Protocol16Handler.DoPing(serverIP, serverPort, ref protocolversionTmp)) { success = true; } @@ -124,7 +123,7 @@ namespace MinecraftClient.Protocol /// Protocol version to handle /// Handler with the appropriate callbacks /// - public static IMinecraftCom GetProtocolHandler(TcpClient Client, int ProtocolVersion, ForgeInfo forgeInfo, IMinecraftComHandler Handler) + public static IMinecraftCom GetProtocolHandler(TcpClient Client, int ProtocolVersion, ForgeInfo? forgeInfo, IMinecraftComHandler Handler) { int[] supportedVersions_Protocol16 = { 51, 60, 61, 72, 73, 74, 78 }; @@ -728,7 +727,7 @@ namespace MinecraftClient.Protocol /// List of ID of available Realms worlds public static List RealmsListWorlds(string username, string uuid, string accesstoken) { - List realmsWorldsResult = new List(); // Store world ID + List realmsWorldsResult = new(); // Store world ID try { string result = ""; @@ -739,7 +738,7 @@ namespace MinecraftClient.Protocol && realmsWorlds.Properties["servers"].Type == Json.JSONData.DataType.Array && realmsWorlds.Properties["servers"].DataArray.Count > 0) { - List availableWorlds = new List(); // Store string to print + List availableWorlds = new(); // Store string to print int index = 0; foreach (Json.JSONData realmsServer in realmsWorlds.Properties["servers"].DataArray) { @@ -833,17 +832,19 @@ namespace MinecraftClient.Protocol /// HTTP Status code private static int DoHTTPSGet(string host, string endpoint, string cookies, ref string result) { - List http_request = new List(); - http_request.Add("GET " + endpoint + " HTTP/1.1"); - http_request.Add("Cookie: " + cookies); - http_request.Add("Cache-Control: no-cache"); - http_request.Add("Pragma: no-cache"); - http_request.Add("Host: " + host); - http_request.Add("User-Agent: Java/1.6.0_27"); - http_request.Add("Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7"); - http_request.Add("Connection: close"); - http_request.Add(""); - http_request.Add(""); + List http_request = new() + { + "GET " + endpoint + " HTTP/1.1", + "Cookie: " + cookies, + "Cache-Control: no-cache", + "Pragma: no-cache", + "Host: " + host, + "User-Agent: Java/1.6.0_27", + "Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7", + "Connection: close", + "", + "" + }; return DoHTTPSRequest(http_request, host, ref result); } @@ -857,15 +858,17 @@ namespace MinecraftClient.Protocol /// HTTP Status code private static int DoHTTPSPost(string host, string endpoint, string request, ref string result) { - List http_request = new List(); - http_request.Add("POST " + endpoint + " HTTP/1.1"); - http_request.Add("Host: " + host); - http_request.Add("User-Agent: MCC/" + Program.Version); - http_request.Add("Content-Type: application/json"); - http_request.Add("Content-Length: " + Encoding.ASCII.GetBytes(request).Length); - http_request.Add("Connection: close"); - http_request.Add(""); - http_request.Add(request); + List http_request = new() + { + "POST " + endpoint + " HTTP/1.1", + "Host: " + host, + "User-Agent: MCC/" + Program.Version, + "Content-Type: application/json", + "Content-Length: " + Encoding.ASCII.GetBytes(request).Length, + "Connection: close", + "", + request + }; return DoHTTPSRequest(http_request, host, ref result); } @@ -889,8 +892,8 @@ namespace MinecraftClient.Protocol if (Settings.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("debug.request", host)); - TcpClient client = ProxyHandler.newTcpClient(host, 443, true); - SslStream stream = new SslStream(client.GetStream()); + TcpClient client = ProxyHandler.NewTcpClient(host, 443, true); + SslStream stream = new(client.GetStream()); stream.AuthenticateAsClient(host, null, SslProtocols.Tls12, true); // Enable TLS 1.2. Hotfix for #1780 if (Settings.DebugMessages) @@ -898,7 +901,7 @@ namespace MinecraftClient.Protocol ConsoleIO.WriteLineFormatted("§8> " + line); stream.Write(Encoding.ASCII.GetBytes(String.Join("\r\n", headers.ToArray()))); - System.IO.StreamReader sr = new System.IO.StreamReader(stream); + System.IO.StreamReader sr = new(stream); string raw_result = sr.ReadToEnd(); if (Settings.DebugMessages) @@ -910,14 +913,14 @@ namespace MinecraftClient.Protocol if (raw_result.StartsWith("HTTP/1.1")) { - postResult = raw_result.Substring(raw_result.IndexOf("\r\n\r\n") + 4); + postResult = raw_result[(raw_result.IndexOf("\r\n\r\n") + 4)..]; statusCode = Settings.str2int(raw_result.Split(' ')[1]); } else statusCode = 520; //Web server is returning an unknown error } catch (Exception e) { - if (!(e is System.Threading.ThreadAbortException)) + if (e is not System.Threading.ThreadAbortException) { exception = e; } @@ -938,7 +941,7 @@ namespace MinecraftClient.Protocol /// Encoded text private static string JsonEncode(string text) { - StringBuilder result = new StringBuilder(); + StringBuilder result = new(); foreach (char c in text) { @@ -965,7 +968,7 @@ namespace MinecraftClient.Protocol public static DateTime UnixTimeStampToDateTime(long unixTimeStamp) { // Unix timestamp is seconds past epoch - DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + DateTime dateTime = new(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); dateTime = dateTime.AddSeconds(unixTimeStamp).ToLocalTime(); return dateTime; } diff --git a/MinecraftClient/Protocol/ProxiedWebRequest.cs b/MinecraftClient/Protocol/ProxiedWebRequest.cs index 34603230..e402234d 100644 --- a/MinecraftClient/Protocol/ProxiedWebRequest.cs +++ b/MinecraftClient/Protocol/ProxiedWebRequest.cs @@ -1,13 +1,12 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.IO; using System.Collections.Specialized; -using System.Net.Sockets; -using MinecraftClient.Proxy; +using System.IO; using System.Net.Security; +using System.Net.Sockets; using System.Security.Authentication; +using System.Text; +using MinecraftClient.Proxy; namespace MinecraftClient.Protocol { @@ -18,16 +17,16 @@ namespace MinecraftClient.Protocol { private readonly string httpVersion = "HTTP/1.0"; // Use 1.0 here because 1.1 server may send chunked data - private Uri uri; - private string host { get { return uri.Host; } } - private int port { get { return uri.Port; } } - private string path { get { return uri.PathAndQuery; } } - private bool isSecure { get { return uri.Scheme == "https"; } } + private readonly Uri uri; + private string Host { get { return uri.Host; } } + private int Port { get { return uri.Port; } } + private string Path { get { return uri.PathAndQuery; } } + private bool IsSecure { get { return uri.Scheme == "https"; } } - public NameValueCollection Headers = new NameValueCollection(); + public NameValueCollection Headers = new(); - public string UserAgent { get { return Headers.Get("User-Agent"); } set { Headers.Set("User-Agent", value); } } - public string Accept { get { return Headers.Get("Accept"); } set { Headers.Set("Accept", value); } } + public string UserAgent { get { return Headers.Get("User-Agent") ?? String.Empty; } set { Headers.Set("User-Agent", value); } } + public string Accept { get { return Headers.Get("Accept") ?? String.Empty; } set { Headers.Set("Accept", value); } } public string Cookie { set { Headers.Set("Cookie", value); } } /// @@ -57,7 +56,7 @@ namespace MinecraftClient.Protocol /// private void SetupBasicHeaders() { - Headers.Add("Host", host); + Headers.Add("Host", Host); Headers.Add("User-Agent", "MCC/" + Program.Version); Headers.Add("Accept", "*/*"); Headers.Add("Connection", "close"); @@ -94,9 +93,9 @@ namespace MinecraftClient.Protocol /// private Response Send(string method, string body = "") { - List requestMessage = new List() + List requestMessage = new() { - string.Format("{0} {1} {2}", method.ToUpper(), path, httpVersion) // Request line + string.Format("{0} {1} {2}", method.ToUpper(), Path, httpVersion) // Request line }; foreach (string key in Headers) // Headers { @@ -119,12 +118,12 @@ namespace MinecraftClient.Protocol Response response = Response.Empty(); AutoTimeout.Perform(() => { - TcpClient client = ProxyHandler.newTcpClient(host, port, true); + TcpClient client = ProxyHandler.NewTcpClient(Host, Port, true); Stream stream; - if (isSecure) + if (IsSecure) { stream = new SslStream(client.GetStream()); - ((SslStream)stream).AuthenticateAsClient(host, null, SslProtocols.Tls12, true); // Enable TLS 1.2. Hotfix for #1774 + ((SslStream)stream).AuthenticateAsClient(Host, null, SslProtocols.Tls12, true); // Enable TLS 1.2. Hotfix for #1774 } else { @@ -134,7 +133,7 @@ namespace MinecraftClient.Protocol byte[] data = Encoding.ASCII.GetBytes(h); stream.Write(data, 0, data.Length); stream.Flush(); - StreamReader sr = new StreamReader(stream); + StreamReader sr = new(stream); string rawResult = sr.ReadToEnd(); response = ParseResponse(rawResult); try @@ -142,8 +141,9 @@ namespace MinecraftClient.Protocol sr.Close(); stream.Close(); client.Close(); - } catch { } - }, + } + catch { } + }, TimeSpan.FromSeconds(30)); return response; } @@ -157,13 +157,13 @@ namespace MinecraftClient.Protocol { int statusCode; string responseBody = ""; - NameValueCollection headers = new NameValueCollection(); - NameValueCollection cookies = new NameValueCollection(); + NameValueCollection headers = new(); + NameValueCollection cookies = new(); if (raw.StartsWith("HTTP/1.1") || raw.StartsWith("HTTP/1.0")) { - Queue msg = new Queue(raw.Split(new string[] { "\r\n" }, StringSplitOptions.None)); + Queue msg = new(raw.Split(new string[] { "\r\n" }, StringSplitOptions.None)); statusCode = int.Parse(msg.Dequeue().Split(' ')[1]); - + while (msg.Peek() != "") { string[] header = msg.Dequeue().Split(new char[] { ':' }, 2); // Split first ':' only @@ -183,26 +183,14 @@ namespace MinecraftClient.Protocol } } msg.Dequeue(); - if (msg.Count > 0) + if (msg.Count > 0) responseBody = msg.Dequeue(); - return new Response() - { - StatusCode = statusCode, - Body = responseBody, - Headers = headers, - Cookies = cookies - }; + return new Response(statusCode, responseBody, headers, cookies); } else { - return new Response() - { - StatusCode = 520, // 502 - Web Server Returned an Unknown Error - Body = "", - Headers = headers, - Cookies = cookies - }; + return new Response(520 /* Web Server Returned an Unknown Error */, "", headers, cookies); } } @@ -233,19 +221,21 @@ namespace MinecraftClient.Protocol public NameValueCollection Headers; public NameValueCollection Cookies; + public Response(int statusCode, string body, NameValueCollection headers, NameValueCollection cookies) + { + StatusCode = statusCode; + Body = body; + Headers = headers; + Cookies = cookies; + } + /// /// Get an empty response object /// /// public static Response Empty() { - return new Response() - { - StatusCode = 204, // 204 - No content - Body = "", - Headers = new NameValueCollection(), - Cookies = new NameValueCollection() - }; + return new Response(204 /* No content */, "", new NameValueCollection(), new NameValueCollection()); } public override string ToString() @@ -274,7 +264,7 @@ namespace MinecraftClient.Protocol sb.AppendLine("Body: (Truncated to 200 characters)"); } else sb.AppendLine("Body: "); - sb.AppendLine(Body.Length > 200 ? Body.Substring(0, 200) + "..." : Body); + sb.AppendLine(Body.Length > 200 ? Body[..200] + "..." : Body); } return sb.ToString(); } diff --git a/MinecraftClient/Protocol/ReplayHandler.cs b/MinecraftClient/Protocol/ReplayHandler.cs index d63f5164..610273e3 100644 --- a/MinecraftClient/Protocol/ReplayHandler.cs +++ b/MinecraftClient/Protocol/ReplayHandler.cs @@ -1,12 +1,10 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.IO; -using MinecraftClient.Protocol.Handlers; -using System.Runtime.InteropServices; +using System.Linq; using Ionic.Zip; using MinecraftClient.Mapping; +using MinecraftClient.Protocol.Handlers; using MinecraftClient.Protocol.Handlers.PacketPalettes; namespace MinecraftClient.Protocol @@ -23,16 +21,16 @@ namespace MinecraftClient.Protocol private readonly string recordingTmpFileName = @"recording.tmcpr"; private readonly string temporaryCache = @"recording_cache"; - private DataTypes dataTypes; - private PacketTypePalette packetType; - private int protocolVersion; - private BinaryWriter recordStream; - private DateTime recordStartTime; + private readonly DataTypes dataTypes; + private readonly PacketTypePalette packetType; + private readonly int protocolVersion; + private readonly BinaryWriter? recordStream; + private readonly DateTime recordStartTime; private DateTime lastPacketTime; private bool prepareCleanUp = false; private bool cleanedUp = false; - private static bool logOutput = true; + private static readonly bool logOutput = true; private int playerEntityID; private Guid playerUUID; @@ -42,20 +40,8 @@ namespace MinecraftClient.Protocol public ReplayHandler(int protocolVersion) { - Initialize(protocolVersion); - } - - public ReplayHandler(int protocolVersion, string serverName, string recordingDirectory = @"replay_recordings") - { - Initialize(protocolVersion); - this.MetaData.serverName = serverName; - ReplayFileDirectory = recordingDirectory; - } - - private void Initialize(int protocolVersion) - { - this.dataTypes = new DataTypes(protocolVersion); - this.packetType = new PacketTypeHandler().GetTypeHandler(protocolVersion); + dataTypes = new DataTypes(protocolVersion); + packetType = new PacketTypeHandler().GetTypeHandler(protocolVersion); this.protocolVersion = protocolVersion; if (!Directory.Exists(ReplayFileDirectory)) @@ -66,16 +52,28 @@ namespace MinecraftClient.Protocol recordStream = new BinaryWriter(new FileStream(Path.Combine(temporaryCache, recordingTmpFileName), FileMode.Create, FileAccess.ReadWrite)); recordStartTime = DateTime.Now; - MetaData = new MetaDataHandler(); - MetaData.date = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds; - MetaData.protocol = protocolVersion; - MetaData.mcversion = ProtocolHandler.ProtocolVersion2MCVer(protocolVersion); + MetaData = new MetaDataHandler + { + date = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds, + protocol = protocolVersion, + mcversion = ProtocolHandler.ProtocolVersion2MCVer(protocolVersion) + }; MetaData.SaveToFile(); playerLastPosition = new Location(0, 0, 0); WriteLog("Start recording."); } + public ReplayHandler(int protocolVersion, string serverName, string recordingDirectory = @"replay_recordings") + : this(protocolVersion) + { + dataTypes = new DataTypes(protocolVersion); + packetType = new PacketTypeHandler().GetTypeHandler(protocolVersion); + + MetaData.serverName = serverName; + ReplayFileDirectory = recordingDirectory; + } + ~ReplayHandler() { OnShutDown(); @@ -97,7 +95,7 @@ namespace MinecraftClient.Protocol { try { - recordStream.Flush(); + recordStream!.Flush(); recordStream.Close(); } catch { } @@ -139,17 +137,13 @@ namespace MinecraftClient.Protocol using (Stream recordingFile = new FileStream(Path.Combine(temporaryCache, recordingTmpFileName), FileMode.Open)) { - using (Stream metaDataFile = new FileStream(Path.Combine(temporaryCache, MetaData.MetaDataFileName), FileMode.Open)) - { - using (ZipOutputStream zs = new ZipOutputStream(Path.Combine(ReplayFileDirectory, replayFileName))) - { - zs.PutNextEntry(recordingTmpFileName); - recordingFile.CopyTo(zs); - zs.PutNextEntry(MetaData.MetaDataFileName); - metaDataFile.CopyTo(zs); - zs.Close(); - } - } + using Stream metaDataFile = new FileStream(Path.Combine(temporaryCache, MetaData.MetaDataFileName), FileMode.Open); + using ZipOutputStream zs = new(Path.Combine(ReplayFileDirectory, replayFileName)); + zs.PutNextEntry(recordingTmpFileName); + recordingFile.CopyTo(zs); + zs.PutNextEntry(MetaData.MetaDataFileName); + metaDataFile.CopyTo(zs); + zs.Close(); } File.Delete(Path.Combine(temporaryCache, recordingTmpFileName)); @@ -173,20 +167,18 @@ namespace MinecraftClient.Protocol using (Stream metaDataFile = new FileStream(Path.Combine(temporaryCache, MetaData.MetaDataFileName), FileMode.Open)) { - using (ZipOutputStream zs = new ZipOutputStream(replayFileName)) - { - zs.PutNextEntry(recordingTmpFileName); - // .CopyTo() method start from stream current position - // We need to reset position in order to get full content - var lastPosition = recordStream.BaseStream.Position; - recordStream.BaseStream.Position = 0; - recordStream.BaseStream.CopyTo(zs); - recordStream.BaseStream.Position = lastPosition; + using ZipOutputStream zs = new(replayFileName); + zs.PutNextEntry(recordingTmpFileName); + // .CopyTo() method start from stream current position + // We need to reset position in order to get full content + var lastPosition = recordStream!.BaseStream.Position; + recordStream.BaseStream.Position = 0; + recordStream.BaseStream.CopyTo(zs); + recordStream.BaseStream.Position = lastPosition; - zs.PutNextEntry(MetaData.MetaDataFileName); - metaDataFile.CopyTo(zs); - zs.Close(); - } + zs.PutNextEntry(MetaData.MetaDataFileName); + metaDataFile.CopyTo(zs); + zs.Close(); } WriteDebugLog("Backup replay file created."); @@ -215,7 +207,7 @@ namespace MinecraftClient.Protocol /// public void AddPacket(int packetID, IEnumerable packetData, bool isLogin, bool isInbound) { - try + try { if (isInbound) HandleInBoundPacket(packetID, packetData, isLogin); @@ -240,18 +232,18 @@ namespace MinecraftClient.Protocol lastPacketTime = DateTime.Now; // build raw packet // format: packetID + packetData - List rawPacket = new List(); + List rawPacket = new(); rawPacket.AddRange(dataTypes.GetVarInt(packetID).ToArray()); rawPacket.AddRange(packetData.ToArray()); // build format // format: timestamp + packetLength + RawPacket - List line = new List(); + List line = new(); int nowTime = Convert.ToInt32((lastPacketTime - recordStartTime).TotalMilliseconds); line.AddRange(BitConverter.GetBytes((Int32)nowTime).Reverse().ToArray()); line.AddRange(BitConverter.GetBytes((Int32)rawPacket.Count).Reverse().ToArray()); line.AddRange(rawPacket.ToArray()); // Write out to the file - recordStream.Write(line.ToArray()); + recordStream!.Write(line.ToArray()); } /// @@ -301,15 +293,14 @@ namespace MinecraftClient.Protocol /// private void HandleInBoundPacket(int packetID, IEnumerable packetData, bool isLogin) { - Queue p = new Queue(packetData); + Queue p = new(packetData); PacketTypesIn pType = packetType.GetIncommingTypeById(packetID); // Login success. Get player UUID if (isLogin && packetID == 0x02) { - Guid uuid; if (protocolVersion < Protocol18Handler.MC_1_16_Version) { - if (Guid.TryParse(dataTypes.ReadNextString(p), out uuid)) + if (Guid.TryParse(dataTypes.ReadNextString(p), out Guid uuid)) { SetClientPlayerUUID(uuid); WriteDebugLog("User UUID: " + uuid.ToString()); @@ -384,7 +375,7 @@ namespace MinecraftClient.Protocol private byte[] GetSpawnPlayerPacket(int entityID, Guid playerUUID, Location location, double pitch, double yaw) { - List packet = new List(); + List packet = new(); packet.AddRange(dataTypes.GetVarInt(entityID)); packet.AddRange(playerUUID.ToBigEndianBytes()); packet.AddRange(dataTypes.GetDouble(location.X)); @@ -423,7 +414,7 @@ namespace MinecraftClient.Protocol public readonly string temporaryCache = @"recording_cache"; public bool singlePlayer = false; - public string serverName; + public string? serverName; public int duration = 0; // duration of the whole replay public long date; // start time of the recording in unix timestamp milliseconds public string mcversion = "0.0"; // e.g. 1.15.2 diff --git a/MinecraftClient/Protocol/Session/SessionCache.cs b/MinecraftClient/Protocol/Session/SessionCache.cs index cb45c091..232c5e5e 100644 --- a/MinecraftClient/Protocol/Session/SessionCache.cs +++ b/MinecraftClient/Protocol/Session/SessionCache.cs @@ -1,5 +1,4 @@ -using MinecraftClient.Protocol; -using System; +using System; using System.Collections.Generic; using System.IO; using System.Runtime.Serialization; @@ -23,11 +22,11 @@ namespace MinecraftClient.Protocol.Session "launcher_profiles.json" ); - private static FileMonitor cachemonitor; - private static Dictionary sessions = new Dictionary(); - private static Timer updatetimer = new Timer(100); - private static List> pendingadds = new List>(); - private static BinaryFormatter formatter = new BinaryFormatter(); + private static FileMonitor? cachemonitor; + private static readonly Dictionary sessions = new(); + private static readonly Timer updatetimer = new(100); + private static readonly List> pendingadds = new(); + private static readonly BinaryFormatter formatter = new(); /// /// Retrieve whether SessionCache contains a session for the given login. @@ -102,12 +101,12 @@ namespace MinecraftClient.Protocol.Session /// /// Sender /// Event data - private static void HandlePending(object sender, ElapsedEventArgs e) + private static void HandlePending(object? sender, ElapsedEventArgs e) { updatetimer.Stop(); LoadFromDisk(); - foreach(KeyValuePair pending in pendingadds.ToArray()) + foreach (KeyValuePair pending in pendingadds.ToArray()) { Store(pending.Key, pending.Value); pendingadds.Remove(pending); @@ -125,7 +124,7 @@ namespace MinecraftClient.Protocol.Session { if (Settings.DebugMessages) ConsoleIO.WriteLineFormatted(Translations.Get("cache.loading", Path.GetFileName(SessionCacheFileMinecraft))); - Json.JSONData mcSession = new Json.JSONData(Json.JSONData.DataType.String); + Json.JSONData mcSession = new(Json.JSONData.DataType.String); try { mcSession = Json.ParseJson(File.ReadAllText(SessionCacheFileMinecraft)); @@ -135,12 +134,11 @@ namespace MinecraftClient.Protocol.Session && mcSession.Properties.ContainsKey("clientToken") && mcSession.Properties.ContainsKey("authenticationDatabase")) { - Guid temp; string clientID = mcSession.Properties["clientToken"].StringValue.Replace("-", ""); Dictionary sessionItems = mcSession.Properties["authenticationDatabase"].Properties; foreach (string key in sessionItems.Keys) { - if (Guid.TryParseExact(key, "N", out temp)) + if (Guid.TryParseExact(key, "N", out Guid temp)) { Dictionary sessionItem = sessionItems[key].Properties; if (sessionItem.ContainsKey("displayName") @@ -176,15 +174,16 @@ namespace MinecraftClient.Protocol.Session try { - using (FileStream fs = new FileStream(SessionCacheFileSerialized, FileMode.Open, FileAccess.Read, FileShare.Read)) + using FileStream fs = new(SessionCacheFileSerialized, FileMode.Open, FileAccess.Read, FileShare.Read); +#pragma warning disable SYSLIB0011 // BinaryFormatter.Deserialize() is obsolete + // Possible risk of information disclosure or remote code execution. The impact of this vulnerability is limited to the user side only. + Dictionary sessionsTemp = (Dictionary)formatter.Deserialize(fs); +#pragma warning restore SYSLIB0011 // BinaryFormatter.Deserialize() is obsolete + foreach (KeyValuePair item in sessionsTemp) { - Dictionary sessionsTemp = (Dictionary)formatter.Deserialize(fs); - foreach (KeyValuePair item in sessionsTemp) - { - if (Settings.DebugMessages) - ConsoleIO.WriteLineFormatted(Translations.Get("cache.loaded", item.Key, item.Value.ID)); - sessions[item.Key] = item.Value; - } + if (Settings.DebugMessages) + ConsoleIO.WriteLineFormatted(Translations.Get("cache.loaded", item.Key, item.Value.ID)); + sessions[item.Key] = item.Value; } } catch (IOException ex) @@ -250,9 +249,11 @@ namespace MinecraftClient.Protocol.Session if (Settings.DebugMessages) Translations.WriteLineFormatted("cache.saving"); - List sessionCacheLines = new List(); - sessionCacheLines.Add("# Generated by MCC v" + Program.Version + " - Keep it secret & Edit at own risk!"); - sessionCacheLines.Add("# Login=SessionID,PlayerName,UUID,ClientID,RefreshToken,ServerIDhash,ServerPublicKey"); + List sessionCacheLines = new() + { + "# Generated by MCC v" + Program.Version + " - Keep it secret & Edit at own risk!", + "# Login=SessionID,PlayerName,UUID,ClientID,RefreshToken,ServerIDhash,ServerPublicKey" + }; foreach (KeyValuePair entry in sessions) sessionCacheLines.Add(entry.Key + '=' + entry.Value.ToString()); diff --git a/MinecraftClient/Protocol/Session/SessionToken.cs b/MinecraftClient/Protocol/Session/SessionToken.cs index 37d7476e..e48567d9 100644 --- a/MinecraftClient/Protocol/Session/SessionToken.cs +++ b/MinecraftClient/Protocol/Session/SessionToken.cs @@ -1,7 +1,6 @@ using System; -using System.Collections.Generic; -using System.Text.RegularExpressions; using System.IO; +using System.Text.RegularExpressions; using System.Threading.Tasks; namespace MinecraftClient.Protocol.Session @@ -9,7 +8,7 @@ namespace MinecraftClient.Protocol.Session [Serializable] public class SessionToken { - private static readonly Regex JwtRegex = new Regex("^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+$"); + private static readonly Regex JwtRegex = new("^[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+\\.[A-Za-z0-9-_]+$"); public string ID { get; set; } public string PlayerName { get; set; } @@ -34,11 +33,10 @@ namespace MinecraftClient.Protocol.Session public bool SessionPreCheck() { - if (this.ID == string.Empty || this.PlayerID == String.Empty || this.ServerPublicKey == null) + if (ID == string.Empty || PlayerID == String.Empty || ServerPublicKey == null) return false; - if (Crypto.CryptoHandler.ClientAESPrivateKey == null) - Crypto.CryptoHandler.ClientAESPrivateKey = Crypto.CryptoHandler.GenerateAESPrivateKey(); - string serverHash = Crypto.CryptoHandler.getServerHash(ServerIDhash, ServerPublicKey, Crypto.CryptoHandler.ClientAESPrivateKey); + Crypto.CryptoHandler.ClientAESPrivateKey ??= Crypto.CryptoHandler.GenerateAESPrivateKey(); + string serverHash = Crypto.CryptoHandler.GetServerHash(ServerIDhash, ServerPublicKey, Crypto.CryptoHandler.ClientAESPrivateKey); if (ProtocolHandler.SessionCheck(PlayerID, ID, serverHash)) return true; return false; @@ -46,7 +44,7 @@ namespace MinecraftClient.Protocol.Session public override string ToString() { - return String.Join(",", ID, PlayerName, PlayerID, ClientID, RefreshToken, ServerIDhash, + return String.Join(",", ID, PlayerName, PlayerID, ClientID, RefreshToken, ServerIDhash, (ServerPublicKey == null) ? String.Empty : Convert.ToBase64String(ServerPublicKey)); } @@ -56,11 +54,13 @@ namespace MinecraftClient.Protocol.Session if (fields.Length < 4) throw new InvalidDataException("Invalid string format"); - SessionToken session = new SessionToken(); - session.ID = fields[0]; - session.PlayerName = fields[1]; - session.PlayerID = fields[2]; - session.ClientID = fields[3]; + SessionToken session = new() + { + ID = fields[0], + PlayerName = fields[1], + PlayerID = fields[2], + ClientID = fields[3] + }; // Backward compatible with old session file without refresh token field if (fields.Length > 4) session.RefreshToken = fields[4]; @@ -83,15 +83,13 @@ namespace MinecraftClient.Protocol.Session } else session.ServerPublicKey = null; - - Guid temp; if (!JwtRegex.IsMatch(session.ID)) throw new InvalidDataException("Invalid session ID"); if (!ChatBot.IsValidName(session.PlayerName)) throw new InvalidDataException("Invalid player name"); - if (!Guid.TryParseExact(session.PlayerID, "N", out temp)) + if (!Guid.TryParseExact(session.PlayerID, "N", out _)) throw new InvalidDataException("Invalid player ID"); - if (!Guid.TryParseExact(session.ClientID, "N", out temp)) + if (!Guid.TryParseExact(session.ClientID, "N", out _)) throw new InvalidDataException("Invalid client ID"); // No validation on refresh token because it is custom format token (not Jwt) diff --git a/MinecraftClient/Proxy/ProxyHandler.cs b/MinecraftClient/Proxy/ProxyHandler.cs index 9dbd1086..b62459bb 100644 --- a/MinecraftClient/Proxy/ProxyHandler.cs +++ b/MinecraftClient/Proxy/ProxyHandler.cs @@ -13,8 +13,8 @@ namespace MinecraftClient.Proxy { public enum Type { HTTP, SOCKS4, SOCKS4a, SOCKS5 }; - private static ProxyClientFactory factory = new ProxyClientFactory(); - private static IProxyClient proxy; + private static readonly ProxyClientFactory factory = new(); + private static IProxyClient? proxy; private static bool proxy_ok = false; /// @@ -24,7 +24,7 @@ namespace MinecraftClient.Proxy /// Target port /// True if the purpose is logging in to a Minecraft account - public static TcpClient newTcpClient(string host, int port, bool login = false) + public static TcpClient NewTcpClient(string host, int port, bool login = false) { try { diff --git a/MinecraftClient/Resources/config/MinecraftClient.ini b/MinecraftClient/Resources/config/MinecraftClient.ini index 5ec3aeb8..a072d60a 100644 --- a/MinecraftClient/Resources/config/MinecraftClient.ini +++ b/MinecraftClient/Resources/config/MinecraftClient.ini @@ -216,12 +216,11 @@ listfile=autoattack-list.txt [AutoFishing] # Automatically catch fish using a fishing rod -# You need to enable Entity Handling to use this bot -# You should also enable Inventory Handling to keep track of the fishing rod, although not mandatory +# Guide: https://mccteam.github.io/guide/chat-bots.html#auto-fishing # /!\ Make sure server rules allow automated farming before using this bot enabled=false antidespawn=false -main_hand=true # Use the main hand or the second hand to hold the rod. +main_hand=true # Use the main hand or the off hand to hold the rod. auto_start=true # Whether to start fishing automatically after entering a world. cast_delay=0.4 # How soon to re-cast after successful fishing. fishing_delay=3.0 # How long after entering the game to start fishing (seconds). @@ -232,7 +231,7 @@ stationary_threshold=0.001 # Hooks moving in the X and Z axes below this hook_threshold=0.2 # A stationary hook moving on the Y-axis above this threshold will be considered to have caught a fish. log_fishing_bobber=false # For debugging purposes, you can use this log to adjust the two thresholds mentioned above. location= # Some plugins do not allow the player to fish in one place. This allows the player to change position/angle after each fish caught. - # Floating point numbers can be used for both coordinates and angles. Leave blank to disable this function. + # Floating-point numbers can be used for both coordinates and angles. Leave blank to disable this function. # Change the angle only (recommended): location=yaw_1, pitch_1; yaw_2, pitch_2; ...; yaw_n, pitch_n # Change position only: location=x1, y1, z1; x2, y2, z2; ...; xn, yn, zn # Change both angle and position: location=x1, y1, z1, yaw_1, pitch_1; x2, y2, z2, yaw_2, pitch_2; ... ;xn, yn, zn, yaw_n, pitch_n diff --git a/MinecraftClient/Scripting/CSharpRunner.cs b/MinecraftClient/Scripting/CSharpRunner.cs index 6837a1b0..65ea78a3 100644 --- a/MinecraftClient/Scripting/CSharpRunner.cs +++ b/MinecraftClient/Scripting/CSharpRunner.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Generic; -using System.Text; -using System.IO; -using System.Reflection; -using System.Threading; using System.ComponentModel; +using System.IO; using System.Linq; +using System.Text; using DynamicRun.Builder; namespace MinecraftClient @@ -15,7 +13,7 @@ namespace MinecraftClient /// class CSharpRunner { - private static readonly Dictionary CompileCache = new Dictionary(); + private static readonly Dictionary CompileCache = new(); /// /// Run the specified C# script file @@ -27,7 +25,7 @@ namespace MinecraftClient /// Set to false to compile and cache the script without launching it /// Thrown if an error occured /// Result of the execution, returned by the script - public static object? Run(ChatBot apiHandler, string[] lines, string[] args, Dictionary localVars, bool run = true) + public static object? Run(ChatBot apiHandler, string[] lines, string[] args, Dictionary? localVars, bool run = true) { //Script compatibility check for handling future versions differently if (lines.Length < 1 || lines[0] != "//MCCScript 1.0") @@ -37,9 +35,9 @@ namespace MinecraftClient //Script hash for determining if it was previously compiled ulong scriptHash = QuickHash(lines); byte[]? assembly = null; - - Compiler compiler = new Compiler(); - CompileRunner runner = new CompileRunner(); + + Compiler compiler = new(); + CompileRunner runner = new(); //No need to compile two scripts at the same time lock (CompileCache) @@ -49,10 +47,10 @@ namespace MinecraftClient { //Process different sections of the script file bool scriptMain = true; - List script = new List(); - List extensions = new List(); - List libs = new List(); - List dlls = new List(); + List script = new(); + List extensions = new(); + List libs = new(); + List dlls = new(); foreach (string line in lines) { if (line.StartsWith("//using")) @@ -105,7 +103,7 @@ namespace MinecraftClient //Compile the C# class in memory using all the currently loaded assemblies var result = compiler.Compile(code, Guid.NewGuid().ToString()); - + //Process compile warnings and errors if (result.Failures != null) throw new CSharpException(CSErrorType.LoadError, @@ -123,7 +121,8 @@ namespace MinecraftClient //Run the compiled assembly with exception handling if (run) { - try { + try + { var compiled = runner.Execute(assembly!, args, localVars, apiHandler); return compiled; } @@ -164,10 +163,10 @@ namespace MinecraftClient /// public class CSharpException : Exception { - private CSErrorType _type; + private readonly CSErrorType _type; public CSErrorType ExceptionType { get { return _type; } } - public override string Message { get { return InnerException.Message; } } - public override string ToString() { return InnerException.ToString(); } + public override string Message { get { return InnerException!.Message; } } + public override string ToString() { return InnerException!.ToString(); } public CSharpException(CSErrorType type, Exception inner) : base(inner != null ? inner.Message : "", inner) { @@ -183,7 +182,7 @@ namespace MinecraftClient /// /// Holds local variables passed along with the script /// - private Dictionary localVars; + private readonly Dictionary? localVars; /// /// Create a new C# API Wrapper @@ -191,7 +190,7 @@ namespace MinecraftClient /// ChatBot API Handler /// ChatBot tick handler /// Local variables passed along with the script - public CSharpAPI(ChatBot apiHandler, Dictionary localVars) + public CSharpAPI(ChatBot apiHandler, Dictionary? localVars) { SetMaster(apiHandler); this.localVars = localVars; @@ -215,8 +214,7 @@ namespace MinecraftClient /// TRUE if successfully sent (Deprectated, always returns TRUE for compatibility purposes with existing scripts) public bool SendText(object text) { - base.SendText(text is string ? (string)text : text.ToString()); - return true; + return base.SendText(text is string str ? str : (text.ToString() ?? string.Empty)); } /// @@ -225,12 +223,10 @@ namespace MinecraftClient /// The command to process /// Local variables passed along with the internal command /// TRUE if the command was indeed an internal MCC command - new public bool PerformInternalCommand(string command, Dictionary localVars = null) + new public bool PerformInternalCommand(string command, Dictionary? localVars = null) { - if (localVars == null) - localVars = this.localVars; - bool result = base.PerformInternalCommand(command, localVars); - return result; + localVars ??= this.localVars; + return base.PerformInternalCommand(command, localVars); } /// @@ -243,7 +239,8 @@ namespace MinecraftClient { if (extraAttempts == -999999) base.ReconnectToTheServer(); - else base.ReconnectToTheServer(extraAttempts); + else + base.ReconnectToTheServer(extraAttempts); } /// @@ -291,11 +288,12 @@ namespace MinecraftClient /// /// Name of the variable /// Value of the variable or null if no variable - public object GetVar(string varName) + public object? GetVar(string varName) { if (localVars != null && localVars.ContainsKey(varName)) return localVars[varName]; - return Settings.GetVar(varName); + else + return Settings.GetVar(varName); } /// @@ -317,26 +315,26 @@ namespace MinecraftClient /// Variable type /// Variable name /// Variable as specified type or default value for this type - public T GetVar(string varName) + public T? GetVar(string varName) { - object value = GetVar(varName); - if (value is T) - return (T)value; + object? value = GetVar(varName); + if (value is T Tval) + return Tval; if (value != null) { try { TypeConverter converter = TypeDescriptor.GetConverter(typeof(T)); if (converter != null) - return (T)converter.ConvertFromString(value.ToString()); + return (T?)converter.ConvertFromString(value.ToString() ?? string.Empty); } catch (NotSupportedException) { /* Was worth trying */ } } - return default(T); + return default; } //Named shortcuts for GetVar(varname) - public string GetVarAsString(string varName) { return GetVar(varName); } + public string? GetVarAsString(string varName) { return GetVar(varName); } public int GetVarAsInt(string varName) { return GetVar(varName); } public double GetVarAsDouble(string varName) { return GetVar(varName); } public bool GetVarAsBool(string varName) { return GetVar(varName); } @@ -374,12 +372,18 @@ namespace MinecraftClient /// Script to call /// Arguments to pass to the script /// An object returned by the script, or null - public object CallScript(string script, string[] args) + public object? CallScript(string script, string[] args) { - string[] lines = null; ChatBots.Script.LookForScript(ref script); - try { lines = File.ReadAllLines(script, Encoding.UTF8); } - catch (Exception e) { throw new CSharpException(CSErrorType.FileReadError, e); } + string[] lines; + try + { + lines = File.ReadAllLines(script, Encoding.UTF8); + } + catch (Exception e) + { + throw new CSharpException(CSErrorType.FileReadError, e); + } return CSharpRunner.Run(this, lines, args, localVars); } } diff --git a/MinecraftClient/Scripting/ChatBot.cs b/MinecraftClient/Scripting/ChatBot.cs index 6671ad26..b5016d87 100644 --- a/MinecraftClient/Scripting/ChatBot.cs +++ b/MinecraftClient/Scripting/ChatBot.cs @@ -1,9 +1,8 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; -using System.IO; -using System.Threading; using System.Text.RegularExpressions; using MinecraftClient.Inventory; using MinecraftClient.Mapping; @@ -32,17 +31,17 @@ namespace MinecraftClient public enum DisconnectReason { InGameKick, LoginRejected, ConnectionLost, UserLogout }; //Handler will be automatically set on bot loading, don't worry about this - public void SetHandler(McClient handler) { this._handler = handler; } + public void SetHandler(McClient handler) { _handler = handler; } protected void SetMaster(ChatBot master) { this.master = master; } protected void LoadBot(ChatBot bot) { Handler.BotUnLoad(bot); Handler.BotLoad(bot); } protected List GetLoadedChatBots() { return Handler.GetLoadedChatBots(); } protected void UnLoadBot(ChatBot bot) { Handler.BotUnLoad(bot); } - private McClient _handler = null; - private ChatBot master = null; - private List registeredPluginChannels = new List(); - private List registeredCommands = new List(); - private object delayTasksLock = new object(); - private List delayedTasks = new List(); + private McClient? _handler = null; + private ChatBot? master = null; + private readonly List registeredPluginChannels = new(); + private readonly List registeredCommands = new(); + private readonly object delayTasksLock = new(); + private readonly List delayedTasks = new(); private McClient Handler { get @@ -67,7 +66,7 @@ namespace MinecraftClient { if (delayedTasks.Count > 0) { - List tasksToRemove = new List(); + List tasksToRemove = new(); for (int i = 0; i < delayedTasks.Count; i++) { if (delayedTasks[i].Tick()) @@ -310,7 +309,7 @@ namespace MinecraftClient /// Entity /// Equipment slot. 0: main hand, 1: off hand, 2–5: armor slot (2: boots, 3: leggings, 4: chestplate, 5: helmet) /// Item) - public virtual void OnEntityEquipment(Entity entity, int slot, Item item) { } + public virtual void OnEntityEquipment(Entity entity, int slot, Item? item) { } /// /// Called when an entity has effect applied @@ -439,9 +438,9 @@ namespace MinecraftClient /// The command to process /// Local variables passed along with the command /// TRUE if the command was indeed an internal MCC command - protected bool PerformInternalCommand(string command, Dictionary localVars = null) + protected bool PerformInternalCommand(string command, Dictionary? localVars = null) { - string temp = ""; + string? temp = ""; return Handler.PerformInternalCommand(command, ref temp, localVars); } @@ -452,7 +451,7 @@ namespace MinecraftClient /// May contain a confirmation or error message after processing the command, or "" otherwise. /// Local variables passed along with the command /// TRUE if the command was indeed an internal MCC command - protected bool PerformInternalCommand(string command, ref string response_msg, Dictionary localVars = null) + protected bool PerformInternalCommand(string command, ref string? response_msg, Dictionary? localVars = null) { return Handler.PerformInternalCommand(command, ref response_msg, localVars); } @@ -460,7 +459,7 @@ namespace MinecraftClient /// /// Remove color codes ("§c") from a text message received from the server /// - public static string GetVerbatim(string text) + public static string GetVerbatim(string? text) { if (String.IsNullOrEmpty(text)) return String.Empty; @@ -534,9 +533,9 @@ namespace MinecraftClient { if (tmp.Length > 4 && tmp[2] == "to" && tmp[3] == "you:") { - message = text.Substring(tmp[0].Length + 18); //MC 1.7 + message = text[(tmp[0].Length + 18)..]; //MC 1.7 } - else message = text.Substring(tmp[0].Length + 10); //MC 1.5 + else message = text[(tmp[0].Length + 10)..]; //MC 1.5 sender = tmp[0]; return IsValidName(sender); } @@ -547,9 +546,9 @@ namespace MinecraftClient else if (text[0] == '[' && tmp.Length > 3 && tmp[1] == "->" && (tmp[2].ToLower() == "me]" || tmp[2].ToLower() == "moi]")) //'me' is replaced by 'moi' in french servers { - message = text.Substring(tmp[0].Length + 4 + tmp[2].Length + 1); - sender = tmp[0].Substring(1); - if (sender[0] == '~') { sender = sender.Substring(1); } + message = text[(tmp[0].Length + 4 + tmp[2].Length + 1)..]; + sender = tmp[0][1..]; + if (sender[0] == '~') { sender = sender[1..]; } return IsValidName(sender); } @@ -558,22 +557,22 @@ namespace MinecraftClient else if (text[0] == '[' && tmp.Length > 3 && tmp[1] == "@" && (tmp[2].ToLower() == "me]" || tmp[2].ToLower() == "moi]")) //'me' is replaced by 'moi' in french servers { - message = text.Substring(tmp[0].Length + 4 + tmp[2].Length + 0); - sender = tmp[0].Substring(1); - if (sender[0] == '~') { sender = sender.Substring(1); } + message = text[(tmp[0].Length + 4 + tmp[2].Length + 0)..]; + sender = tmp[0][1..]; + if (sender[0] == '~') { sender = sender[1..]; } return IsValidName(sender); } //Detect Essentials (Bukkit) /me messages with some custom prefix //[Prefix] [Someone -> me] message //[Prefix] [~Someone -> me] message - else if (text[0] == '[' && tmp[0][tmp[0].Length - 1] == ']' + else if (text[0] == '[' && tmp[0][^1] == ']' && tmp[1][0] == '[' && tmp.Length > 4 && tmp[2] == "->" && (tmp[3].ToLower() == "me]" || tmp[3].ToLower() == "moi]")) { - message = text.Substring(tmp[0].Length + 1 + tmp[1].Length + 4 + tmp[3].Length + 1); - sender = tmp[1].Substring(1); - if (sender[0] == '~') { sender = sender.Substring(1); } + message = text[(tmp[0].Length + 1 + tmp[1].Length + 4 + tmp[3].Length + 1)..]; + sender = tmp[1][1..]; + if (sender[0] == '~') { sender = sender[1..]; } return IsValidName(sender); } @@ -583,9 +582,9 @@ namespace MinecraftClient else if (text[0] == '[' && tmp.Length > 3 && tmp[2] == "->" && (tmp[3].ToLower() == "me]" || tmp[3].ToLower() == "moi]")) { - message = text.Substring(tmp[0].Length + 1 + tmp[1].Length + 4 + tmp[2].Length + 1); - sender = tmp[0].Substring(1); - if (sender[0] == '~') { sender = sender.Substring(1); } + message = text[(tmp[0].Length + 1 + tmp[1].Length + 4 + tmp[2].Length + 1)..]; + sender = tmp[0][1..]; + if (sender[0] == '~') { sender = sender[1..]; } return IsValidName(sender); } @@ -593,8 +592,8 @@ namespace MinecraftClient //From Someone: message else if (text.StartsWith("From ")) { - sender = text.Substring(5).Split(':')[0]; - message = text.Substring(text.IndexOf(':') + 2); + sender = text[5..].Split(':')[0]; + message = text[(text.IndexOf(':') + 2)..]; return IsValidName(sender); } else return false; @@ -646,15 +645,15 @@ namespace MinecraftClient { try { - text = text.Substring(1); + text = text[1..]; string[] tmp2 = text.Split('>'); sender = tmp2[0]; - message = text.Substring(sender.Length + 2); + message = text[(sender.Length + 2)..]; if (message.Length > 1 && message[0] == ' ') - { message = message.Substring(1); } + { message = message[1..]; } tmp2 = sender.Split(' '); - sender = tmp2[tmp2.Length - 1]; - if (sender[0] == '~') { sender = sender.Substring(1); } + sender = tmp2[^1]; + if (sender[0] == '~') { sender = sender[1..]; } return IsValidName(sender); } catch (IndexOutOfRangeException) { /* Not a vanilla/faction message */ } @@ -669,9 +668,9 @@ namespace MinecraftClient try { int name_end = text.IndexOf(':'); - int name_start = text.Substring(0, name_end).LastIndexOf(']') + 2; - sender = text.Substring(name_start, name_end - name_start); - message = text.Substring(name_end + 2); + int name_start = text[..name_end].LastIndexOf(']') + 2; + sender = text[name_start..name_end]; + message = text[(name_end + 2)..]; return IsValidName(sender); } catch (IndexOutOfRangeException) { /* Not a herochat message */ } @@ -698,7 +697,7 @@ namespace MinecraftClient if (prefix.All(c => char.IsLetterOrDigit(c) || new char[] { '*', '<', '>', '_' }.Contains(c)) && semicolon == ":") { - message = text.Substring(prefix.Length + user.Length + 4); + message = text[(prefix.Length + user.Length + 4)..]; return IsValidName(user); } } @@ -750,13 +749,12 @@ namespace MinecraftClient || (tmp[0].StartsWith("[") && tmp[0].EndsWith("]"))) && tmp.Length > 1) sender = tmp[1]; - - //Username has requested... - else sender = tmp[0]; + else //Username has requested.. + sender = tmp[0]; //~Username has requested... if (sender.Length > 1 && sender[0] == '~') - sender = sender.Substring(1); + sender = sender[1..]; //Final check on username validity return IsValidName(sender); @@ -770,19 +768,19 @@ namespace MinecraftClient /// Write some text in the console. Nothing will be sent to the server. /// /// Log text to write - protected void LogToConsole(object text) + protected void LogToConsole(object? text) { if (_handler == null || master == null) - ConsoleIO.WriteLogLine(String.Format("[{0}] {1}", this.GetType().Name, text)); + ConsoleIO.WriteLogLine(String.Format("[{0}] {1}", GetType().Name, text)); else - Handler.Log.Info(String.Format("[{0}] {1}", this.GetType().Name, text)); + Handler.Log.Info(String.Format("[{0}] {1}", GetType().Name, text)); string logfile = Settings.ExpandVars(Settings.chatbotLogFile); if (!String.IsNullOrEmpty(logfile)) { if (!File.Exists(logfile)) { - try { Directory.CreateDirectory(Path.GetDirectoryName(logfile)); } + try { Directory.CreateDirectory(Path.GetDirectoryName(logfile)!); } catch { return; /* Invalid path or access denied */ } try { File.WriteAllText(logfile, ""); } catch { return; /* Invalid file name or access denied */ } @@ -817,7 +815,7 @@ namespace MinecraftClient /// /// Translation key /// - protected void LogDebugToConsoleTranslated(string key, params object[] args) + protected void LogDebugToConsoleTranslated(string key, params object?[] args) { LogDebugToConsole(Translations.TryGet(key, args)); } @@ -831,7 +829,7 @@ namespace MinecraftClient protected void ReconnectToTheServer(int ExtraAttempts = 3, int delaySeconds = 0) { if (Settings.DebugMessages) - ConsoleIO.WriteLogLine(Translations.Get("chatbot.reconnect", this.GetType().Name)); + ConsoleIO.WriteLogLine(Translations.Get("chatbot.reconnect", GetType().Name)); McClient.ReconnectionAttemptsLeft = ExtraAttempts; Program.Restart(delaySeconds); } @@ -872,7 +870,7 @@ namespace MinecraftClient /// File name /// Player name to send error messages, if applicable /// Local variables for use in the Script - protected void RunScript(string filename, string playername = null, Dictionary localVars = null) + protected void RunScript(string filename, string? playername = null, Dictionary? localVars = null) { Handler.BotLoad(new ChatBots.Script(filename, playername, localVars)); } @@ -955,11 +953,9 @@ namespace MinecraftClient /// Get the current Minecraft World /// /// Minecraft world or null if associated setting is disabled - protected Mapping.World GetWorld() + protected World GetWorld() { - if (GetTerrainEnabled()) - return Handler.GetWorld(); - return null; + return Handler.GetWorld(); } /// @@ -1078,7 +1074,7 @@ namespace MinecraftClient else { LogToConsole("File not found: " + System.IO.Path.GetFullPath(file)); - return new string[0]; + return Array.Empty(); } } @@ -1181,7 +1177,7 @@ namespace MinecraftClient /// The name of the channel to register protected void RegisterPluginChannel(string channel) { - this.registeredPluginChannels.Add(channel); + registeredPluginChannels.Add(channel); Handler.RegisterPluginChannel(channel, this); } @@ -1191,7 +1187,7 @@ namespace MinecraftClient /// The name of the channel to unregister protected void UnregisterPluginChannel(string channel) { - this.registeredPluginChannels.RemoveAll(chan => chan == channel); + registeredPluginChannels.RemoveAll(chan => chan == channel); Handler.UnregisterPluginChannel(channel, this); } @@ -1207,7 +1203,7 @@ namespace MinecraftClient { if (!sendEvenIfNotRegistered) { - if (!this.registeredPluginChannels.Contains(channel)) + if (!registeredPluginChannels.Contains(channel)) { return false; } @@ -1258,7 +1254,7 @@ namespace MinecraftClient /// Item type /// Item count /// TRUE if item given successfully - protected bool CreativeGive(int slot, ItemType itemType, int count, Dictionary nbt = null) + protected bool CreativeGive(int slot, ItemType itemType, int count, Dictionary? nbt = null) { return Handler.DoCreativeGive(slot, itemType, count, nbt); } @@ -1331,7 +1327,7 @@ namespace MinecraftClient protected Container GetPlayerInventory() { Container container = Handler.GetPlayerInventory(); - return container == null ? null : new Container(container.ID, container.Type, container.Title, container.Items); + return new Container(container.ID, container.Type, container.Title, container.Items); } /// @@ -1591,9 +1587,9 @@ namespace MinecraftClient public override string CmdUsage { get { return _cmdUsage; } } public override string CmdDesc { get { return _cmdDesc; } } - public override string Run(McClient handler, string command, Dictionary localVars) + public override string Run(McClient handler, string command, Dictionary? localVars) { - return this.Runner(command, getArgs(command)); + return Runner(command, GetArgs(command)); } /// @@ -1605,10 +1601,10 @@ namespace MinecraftClient /// Method for handling the command public ChatBotCommand(string cmdName, string cmdDesc, string cmdUsage, CommandRunner callback) { - this._cmdName = cmdName; - this._cmdDesc = cmdDesc; - this._cmdUsage = cmdUsage; - this.Runner = callback; + _cmdName = cmdName; + _cmdDesc = cmdDesc; + _cmdUsage = cmdUsage; + Runner = callback; } } } diff --git a/MinecraftClient/Scripting/DynamicRun/Builder/CompileRunner.cs b/MinecraftClient/Scripting/DynamicRun/Builder/CompileRunner.cs index 004c512b..0bb3b829 100644 --- a/MinecraftClient/Scripting/DynamicRun/Builder/CompileRunner.cs +++ b/MinecraftClient/Scripting/DynamicRun/Builder/CompileRunner.cs @@ -14,7 +14,7 @@ namespace DynamicRun.Builder { internal class CompileRunner { - public object? Execute(byte[] compiledAssembly, string[] args, Dictionary localVars, ChatBot apiHandler) + public object? Execute(byte[] compiledAssembly, string[] args, Dictionary? localVars, ChatBot apiHandler) { var assemblyLoadContextWeakRef = LoadAndExecute(compiledAssembly, args, localVars, apiHandler); @@ -29,20 +29,18 @@ namespace DynamicRun.Builder } [MethodImpl(MethodImplOptions.NoInlining)] - private static Tuple LoadAndExecute(byte[] compiledAssembly, string[] args, Dictionary localVars, ChatBot apiHandler) + private static Tuple LoadAndExecute(byte[] compiledAssembly, string[] args, Dictionary? localVars, ChatBot apiHandler) { - using (var asm = new MemoryStream(compiledAssembly)) - { - var assemblyLoadContext = new SimpleUnloadableAssemblyLoadContext(); + using var asm = new MemoryStream(compiledAssembly); + var assemblyLoadContext = new SimpleUnloadableAssemblyLoadContext(); - var assembly = assemblyLoadContext.LoadFromStream(asm); - var compiledScript = assembly.CreateInstance("ScriptLoader.Script"); - var execResult = compiledScript.GetType().GetMethod("__run").Invoke(compiledScript, new object[] { new CSharpAPI(apiHandler, localVars), args }); - - assemblyLoadContext.Unload(); + var assembly = assemblyLoadContext.LoadFromStream(asm); + var compiledScript = assembly.CreateInstance("ScriptLoader.Script")!; + var execResult = compiledScript.GetType().GetMethod("__run")!.Invoke(compiledScript, new object[] { new CSharpAPI(apiHandler, localVars), args }); - return new (new WeakReference(assemblyLoadContext), execResult); - } + assemblyLoadContext.Unload(); + + return new(new WeakReference(assemblyLoadContext), execResult); } } } \ No newline at end of file diff --git a/MinecraftClient/Scripting/DynamicRun/Builder/Compiler.cs b/MinecraftClient/Scripting/DynamicRun/Builder/Compiler.cs index 3bc7c2ae..8029afe2 100644 --- a/MinecraftClient/Scripting/DynamicRun/Builder/Compiler.cs +++ b/MinecraftClient/Scripting/DynamicRun/Builder/Compiler.cs @@ -18,39 +18,39 @@ using SingleFileExtractor.Core; namespace DynamicRun.Builder { - internal class Compiler + internal class Compiler { public CompileResult Compile(string filepath, string fileName) { ConsoleIO.WriteLogLine($"Starting compilation of: '{fileName}'"); - using (var peStream = new MemoryStream()) + using var peStream = new MemoryStream(); + var result = GenerateCode(filepath, fileName).Emit(peStream); + + if (!result.Success) { - var result = GenerateCode(filepath, fileName).Emit(peStream); + ConsoleIO.WriteLogLine("Compilation done with error."); - if (!result.Success) + var failures = result.Diagnostics.Where(diagnostic => diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error); + + return new CompileResult() { - ConsoleIO.WriteLogLine("Compilation done with error."); - - var failures = result.Diagnostics.Where(diagnostic => diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error); - - return new CompileResult() { - Assembly = null, - HasCompiledSucecssfully = false, - Failures = failures.ToList() - }; - } - - ConsoleIO.WriteLogLine("Compilation done without any error."); - - peStream.Seek(0, SeekOrigin.Begin); - - return new CompileResult() { - Assembly = peStream.ToArray(), - HasCompiledSucecssfully = true, - Failures = null + Assembly = null, + HasCompiledSucecssfully = false, + Failures = failures.ToList() }; } + + ConsoleIO.WriteLogLine("Compilation done without any error."); + + peStream.Seek(0, SeekOrigin.Begin); + + return new CompileResult() + { + Assembly = peStream.ToArray(), + HasCompiledSucecssfully = true, + Failures = null + }; } private static CSharpCompilation GenerateCode(string sourceCode, string fileName) @@ -60,8 +60,8 @@ namespace DynamicRun.Builder var parsedSyntaxTree = SyntaxFactory.ParseSyntaxTree(codeString, options); - var mods = Assembly.GetEntryAssembly().GetModules(); - + var mods = Assembly.GetEntryAssembly()!.GetModules(); + #pragma warning disable IL3000 // System.Private.CoreLib var A = typeof(object).Assembly.Location; @@ -89,18 +89,19 @@ namespace DynamicRun.Builder ExecutableReader e = new(); File.Delete(tempFileName); File.Copy(executablePath, tempFileName); - + // Access the contents of the executable. var viewAccessor = MemoryMappedFile.CreateFromFile(tempFileName, FileMode.Open).CreateViewAccessor(); var manifest = e.ReadManifest(viewAccessor); var files = manifest.Files; - + Stream? assemblyStream; - var assemblyrefs = Assembly.GetEntryAssembly()?.GetReferencedAssemblies().ToList(); - assemblyrefs.Add(new ("MinecraftClient")); - - foreach (var refs in assemblyrefs) { + var assemblyrefs = Assembly.GetEntryAssembly()?.GetReferencedAssemblies().ToList()!; + assemblyrefs.Add(new("MinecraftClient")); + + foreach (var refs in assemblyrefs) + { var loadedAssembly = Assembly.Load(refs); if (string.IsNullOrEmpty(loadedAssembly.Location)) { @@ -118,8 +119,8 @@ namespace DynamicRun.Builder throw new InvalidOperationException("The executable does not contain a referenced assembly. Assembly name: " + refs.Name); } - assemblyStream = GetStreamForFileEntry(viewAccessor, reference); - references.Add(MetadataReference.CreateFromStream(assemblyStream)); + assemblyStream = GetStreamForFileEntry(viewAccessor, reference); + references.Add(MetadataReference.CreateFromStream(assemblyStream!)); continue; } references.Add(MetadataReference.CreateFromFile(loadedAssembly.Location)); @@ -138,29 +139,27 @@ namespace DynamicRun.Builder #pragma warning restore IL3000 return CSharpCompilation.Create($"{fileName}.dll", new[] { parsedSyntaxTree }, - references: references, - options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, + references: references, + options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, optimizationLevel: OptimizationLevel.Release, assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default)); } - + private static Stream? GetStreamForFileEntry(MemoryMappedViewAccessor viewAccessor, FileEntry file) { - var stream = typeof(BundleExtractor).GetMethod("GetStreamForFileEntry", BindingFlags.NonPublic | BindingFlags.Static)!.Invoke(null, new object[] { viewAccessor, file }) as Stream; - - if (stream == null) - { + if (typeof(BundleExtractor).GetMethod("GetStreamForFileEntry", BindingFlags.NonPublic | BindingFlags.Static)!.Invoke(null, new object[] { viewAccessor, file }) is not Stream stream) throw new InvalidOperationException("The executable does not contain the assembly. Assembly name: " + file.RelativePath); - } return stream; } - internal struct CompileResult { + internal struct CompileResult + { internal byte[]? Assembly; internal bool HasCompiledSucecssfully; internal List? Failures; - public CompileResult(bool hasCompiledSucecssfully, List? failures, byte[]? assembly) { + public CompileResult(bool hasCompiledSucecssfully, List? failures, byte[]? assembly) + { HasCompiledSucecssfully = hasCompiledSucecssfully; Failures = failures; Assembly = assembly; diff --git a/MinecraftClient/Scripting/DynamicRun/Builder/SimpleUnloadableAssemblyLoadContext.cs b/MinecraftClient/Scripting/DynamicRun/Builder/SimpleUnloadableAssemblyLoadContext.cs index d8459d9d..de44652c 100644 --- a/MinecraftClient/Scripting/DynamicRun/Builder/SimpleUnloadableAssemblyLoadContext.cs +++ b/MinecraftClient/Scripting/DynamicRun/Builder/SimpleUnloadableAssemblyLoadContext.cs @@ -16,7 +16,7 @@ namespace DynamicRun.Builder { } - protected override Assembly Load(AssemblyName assemblyName) + protected override Assembly? Load(AssemblyName assemblyName) { return null; } diff --git a/MinecraftClient/Settings.cs b/MinecraftClient/Settings.cs index 70ff4a5b..c8cb6106 100644 --- a/MinecraftClient/Settings.cs +++ b/MinecraftClient/Settings.cs @@ -1,17 +1,14 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.IO; -using System.Text.RegularExpressions; -using MinecraftClient.Protocol.Session; -using MinecraftClient.Protocol; -using MinecraftClient.Mapping; -using System.Threading.Tasks; -using System.Collections.Concurrent; +using System.Linq; using System.Runtime.CompilerServices; -using MinecraftClient.ChatBots; -using System.Diagnostics.CodeAnalysis; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using MinecraftClient.Mapping; +using MinecraftClient.Protocol; +using MinecraftClient.Protocol.Session; namespace MinecraftClient { @@ -86,14 +83,14 @@ namespace MinecraftClient public static string TranslationsFile_Website_Index = "https://launchermeta.mojang.com/v1/packages/e5af543d9b3ce1c063a97842c38e50e29f961f00/1.17.json"; public static string TranslationsFile_Website_Download = "http://resources.download.minecraft.net"; public static TimeSpan messageCooldown = TimeSpan.FromSeconds(2); - public static List Bots_Owners = new List(); + public static List Bots_Owners = new(); public static string Language = "en_GB"; public static bool interactiveMode = true; public static char internalCmdChar = '/'; public static bool playerHeadAsIcon = false; public static string chatbotLogFile = ""; public static bool CacheScripts = true; - public static string BrandInfo = MCCBrandInfo; + public static string? BrandInfo = MCCBrandInfo; public static bool DisplaySystemMessages = true; public static bool DisplayXPBarMessages = true; public static bool DisplayChatLinks = true; @@ -131,8 +128,8 @@ namespace MinecraftClient public static bool InfoMessages = true; public static bool WarningMessages = true; public static bool ErrorMessages = true; - public static Regex ChatFilter = null; - public static Regex DebugFilter = null; + public static Regex? ChatFilter = null; + public static Regex? DebugFilter = null; public static FilterModeEnum FilterMode = FilterModeEnum.Blacklist; public static bool LogToFile = false; public static string LogFile = "console-log.txt"; @@ -191,9 +188,9 @@ namespace MinecraftClient //Chat Message Parsing public static bool ChatFormat_Builtins = true; - public static Regex ChatFormat_Public = null; - public static Regex ChatFormat_Private = null; - public static Regex ChatFormat_TeleportRequest = null; + public static Regex? ChatFormat_Public = null; + public static Regex? ChatFormat_Private = null; + public static Regex? ChatFormat_TeleportRequest = null; //Auto Respond public static bool AutoRespond_Enabled = false; @@ -267,12 +264,12 @@ namespace MinecraftClient public static bool Map_Notify_On_First_Update = true; //Custom app variables and Minecraft accounts - private static readonly Dictionary AppVars = new Dictionary(); - private static readonly Dictionary> Accounts = new Dictionary>(); - private static readonly Dictionary> Servers = new Dictionary>(); + private static readonly Dictionary AppVars = new(); + private static readonly Dictionary> Accounts = new(); + private static readonly Dictionary> Servers = new(); //Temporary Server Alias storage when server list is not loaded yet - private static string ServerAliasTemp = null; + private static string? ServerAliasTemp = null; //Mapping for settings sections in the INI file private enum Section { Default, Main, AppVars, Proxy, MCSettings, AntiAFK, Hangman, Alerts, ChatLog, AutoRelog, ScriptScheduler, RemoteControl, ChatFormat, AutoRespond, AutoAttack, AutoFishing, AutoEat, AutoCraft, AutoDrop, Mailer, ReplayMod, FollowPlayer, PlayerListLogger, Map, Logging, Signature }; @@ -284,8 +281,7 @@ namespace MinecraftClient /// Section enum private static Section GetSection(string name) { - Section pMode; - if (Enum.TryParse(name, true, out pMode)) + if (Enum.TryParse(name, true, out Section pMode)) return pMode; return Section.Default; } @@ -341,11 +337,11 @@ namespace MinecraftClient if (argument.StartsWith("--")) { //Load settings as --setting=value and --section.setting=value - if (!argument.Contains("=")) + if (!argument.Contains('=')) throw new ArgumentException(Translations.Get("error.setting.argument_syntax", argument)); Section section = Section.Main; - string argName = argument.Substring(2).Split('=')[0]; - string argValue = argument.Substring(argName.Length + 3); + string argName = argument[2..].Split('=')[0]; + string argValue = argument[(argName.Length + 3)..]; if (argName.Contains('.')) { string sectionName = argName.Split('.')[0]; @@ -431,7 +427,7 @@ namespace MinecraftClient Bots_Owners.Clear(); string lowerArgValue = ToLowerIfNeed(argValue); string[] names = lowerArgValue.Split(','); - if (!argValue.Contains(",") && lowerArgValue.EndsWith(".txt") && File.Exists(argValue)) + if (!argValue.Contains(',') && lowerArgValue.EndsWith(".txt") && File.Exists(argValue)) names = File.ReadAllLines(argValue); foreach (string name in names) if (!String.IsNullOrWhiteSpace(name)) @@ -511,12 +507,12 @@ namespace MinecraftClient return true; case "brandinfo": - switch (ToLowerIfNeed(argValue.Trim())) + BrandInfo = ToLowerIfNeed(argValue.Trim()) switch { - case "mcc": BrandInfo = MCCBrandInfo; break; - case "vanilla": BrandInfo = "vanilla"; break; - default: BrandInfo = null; break; - } + "mcc" => MCCBrandInfo, + "vanilla" => "vanilla", + _ => null, + }; return true; case "resolvesrvrecords": @@ -1142,7 +1138,7 @@ namespace MinecraftClient /// /// Variable name /// The value or null if the variable does not exists - public static object GetVar(string varName) + public static object? GetVar(string varName) { if (AppVars.ContainsKey(varName)) return AppVars[varName]; @@ -1164,15 +1160,15 @@ namespace MinecraftClient /// String to parse /// Optional local variables overriding global variables /// Modifier string - public static string ExpandVars(string str, Dictionary localVars = null) + public static string ExpandVars(string str, Dictionary? localVars = null) { - StringBuilder result = new StringBuilder(); + StringBuilder result = new(); for (int i = 0; i < str.Length; i++) { if (str[i] == '%') { bool varname_ok = false; - StringBuilder var_name = new StringBuilder(); + StringBuilder var_name = new(); for (int j = i + 1; j < str.Length; j++) { diff --git a/MinecraftClient/TaskWithDelay.cs b/MinecraftClient/TaskWithDelay.cs index 55b09495..662c3178 100644 --- a/MinecraftClient/TaskWithDelay.cs +++ b/MinecraftClient/TaskWithDelay.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace MinecraftClient { @@ -10,9 +7,9 @@ namespace MinecraftClient /// class TaskWithDelay { - private Action _task; + private readonly Action _task; private int tickCounter; - private DateTime dateToLaunch; + private readonly DateTime dateToLaunch; public Action Task { get { return _task; } } diff --git a/MinecraftClient/TaskWithResult.cs b/MinecraftClient/TaskWithResult.cs index 2762fb28..90e21e8d 100644 --- a/MinecraftClient/TaskWithResult.cs +++ b/MinecraftClient/TaskWithResult.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading; namespace MinecraftClient @@ -12,12 +9,12 @@ namespace MinecraftClient /// Type of the return value public class TaskWithResult { - private AutoResetEvent resultEvent = new AutoResetEvent(false); - private Func task; - private T result = default(T); - private Exception exception = null; + private readonly AutoResetEvent resultEvent = new(false); + private readonly Func task; + private T? result = default; + private Exception? exception = null; private bool taskRun = false; - private object taskRunLock = new object(); + private readonly object taskRunLock = new(); /// /// Create a new asynchronous task with return value @@ -48,17 +45,16 @@ namespace MinecraftClient get { if (taskRun) - { - return result; - } - else throw new InvalidOperationException("Attempting to retrieve the result of an unfinished task"); + return result!; + else + throw new InvalidOperationException("Attempting to retrieve the result of an unfinished task"); } } /// /// Get the exception thrown by the inner delegate, if any /// - public Exception Exception + public Exception? Exception { get { @@ -120,7 +116,7 @@ namespace MinecraftClient if (exception != null) throw exception; - return result; + return result!; } } } diff --git a/MinecraftClient/Translations.cs b/MinecraftClient/Translations.cs index 587abbcc..1bcf9c16 100644 --- a/MinecraftClient/Translations.cs +++ b/MinecraftClient/Translations.cs @@ -1,9 +1,9 @@ using System; -using System.Text; -using System.Text.RegularExpressions; using System.Collections.Generic; using System.Globalization; using System.IO; +using System.Text; +using System.Text.RegularExpressions; namespace MinecraftClient { @@ -15,25 +15,24 @@ namespace MinecraftClient /// public static class Translations { - private static Dictionary translations; - private static string translationFilePath = "lang" + Path.DirectorySeparatorChar + "mcc"; - private static string defaultTranslation = "en.ini"; - private static Regex translationKeyRegex = new Regex(@"\(\[(.*?)\]\)", RegexOptions.Compiled); // Extract string inside ([ ]) + private static readonly Dictionary translations; + private static readonly string translationFilePath = "lang" + Path.DirectorySeparatorChar + "mcc"; + private static readonly string defaultTranslation = "en.ini"; + private static readonly Regex translationKeyRegex = new(@"\(\[(.*?)\]\)", RegexOptions.Compiled); // Extract string inside ([ ]) /// /// Return a tranlation for the requested text. Support string formatting /// /// text identifier /// returns translation for this identifier - public static string Get(string msgName, params object[] args) + public static string Get(string msgName, params object?[] args) { if (translations.ContainsKey(msgName)) { if (args.Length > 0) - { return string.Format(translations[msgName], args); - } - else return translations[msgName]; + else + return translations[msgName]; } return msgName.ToUpper(); } @@ -45,11 +44,12 @@ namespace MinecraftClient /// /// Translated text or original text if not found /// Useful when not sure msgName is a translation mapping key or a normal text - public static string TryGet(string msgName, params object[] args) + public static string TryGet(string msgName, params object?[] args) { if (translations.ContainsKey(msgName)) return Get(msgName, args); - else return msgName; + else + return msgName; } /// @@ -121,7 +121,7 @@ namespace MinecraftClient ? CultureInfo.CurrentCulture.Name : CultureInfo.CurrentCulture.Parent.Name; string baseDir = AppDomain.CurrentDomain.BaseDirectory; - string langDir = baseDir + ((baseDir.EndsWith(Path.DirectorySeparatorChar) ? String.Empty : Path.DirectorySeparatorChar) + + string langDir = baseDir + ((baseDir.EndsWith(Path.DirectorySeparatorChar) ? String.Empty : Path.DirectorySeparatorChar) + translationFilePath + Path.DirectorySeparatorChar); string langFileSystemLanguage = langDir + systemLanguage + ".ini"; string langFileConfigLanguage = langDir + language + ".ini"; @@ -162,13 +162,13 @@ namespace MinecraftClient continue; if (line.StartsWith("#")) // ignore comment line started with # continue; - if (line[0] == '[' && line[line.Length - 1] == ']') // ignore section + if (line[0] == '[' && line[^1] == ']') // ignore section continue; string translationName = line.Split('=')[0]; if (line.Length > (translationName.Length + 1)) { - string translationValue = line.Substring(translationName.Length + 1).Replace("\\n", "\n"); + string translationValue = line[(translationName.Length + 1)..].Replace("\\n", "\n"); translations[translationName] = translationValue; } } diff --git a/MinecraftClient/WinAPI/ConsoleIcon.cs b/MinecraftClient/WinAPI/ConsoleIcon.cs index ec24d7e1..5d8ee345 100644 --- a/MinecraftClient/WinAPI/ConsoleIcon.cs +++ b/MinecraftClient/WinAPI/ConsoleIcon.cs @@ -1,12 +1,10 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Drawing; +using System.IO; +using System.Net.Http; using System.Runtime.InteropServices; using System.Threading; -using System.Net; -using System.IO; -using System.Drawing; +using System.Threading.Tasks; namespace MinecraftClient.WinAPI { @@ -21,7 +19,7 @@ namespace MinecraftClient.WinAPI [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)] private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam); - + /// /// An application sends the WM_SETICON message to associate a new large or small icon with a window. /// The system displays the large icon in the ALT+TAB dialog box, and the small icon in the window caption. @@ -31,62 +29,71 @@ namespace MinecraftClient.WinAPI SETICON = 0x0080, } - private static void SetWindowIcon(System.Drawing.Icon icon) + private static void SetWindowIcon(System.Drawing.Icon icon) { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { IntPtr mwHandle = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle; - IntPtr result01 = SendMessage(mwHandle, (int)WinMessages.SETICON, 0, icon.Handle); - IntPtr result02 = SendMessage(mwHandle, (int)WinMessages.SETICON, 1, icon.Handle); + SendMessage(mwHandle, (int)WinMessages.SETICON, 0, icon.Handle); + SendMessage(mwHandle, (int)WinMessages.SETICON, 1, icon.Handle); } } /// /// Asynchronously download the player's skin and set the head as console icon /// - public static void setPlayerIconAsync(string playerName) { + public static void SetPlayerIconAsync(string playerName) + { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - Thread t = new Thread(new ThreadStart(delegate + Thread t = new(new ThreadStart(delegate { - HttpWebRequest httpWebRequest = (HttpWebRequest) HttpWebRequest.Create("https://minotar.net/helm/" + playerName + "/100.png"); - try + HttpClient httpClient = new(); + try + { + Task httpWebRequest = httpClient.GetStreamAsync("https://minotar.net/helm/" + playerName + "/100.png"); + httpWebRequest.Wait(); + Stream imageStream = httpWebRequest.Result; + try { - using (HttpWebResponse httpWebReponse = (HttpWebResponse) httpWebRequest.GetResponse()) { - try - { - Bitmap skin = new Bitmap(Image.FromStream(httpWebReponse.GetResponseStream())); //Read skin from network - SetWindowIcon(Icon.FromHandle(skin.GetHicon())); // Windows 10+ (New console) - SetConsoleIcon(skin.GetHicon()); // Windows 8 and lower (Older console) - } - catch (ArgumentException) - { - /* Invalid image in HTTP response */ - } - } + Bitmap skin = new(Image.FromStream(imageStream)); //Read skin from network + SetWindowIcon(Icon.FromHandle(skin.GetHicon())); // Windows 10+ (New console) + SetConsoleIcon(skin.GetHicon()); // Windows 8 and lower (Older console) } - catch (WebException) //Skin not found? Reset to default icon + catch (ArgumentException) { - revertToMCCIcon(); + /* Invalid image in HTTP response */ } + imageStream.Dispose(); + httpWebRequest.Dispose(); + } + catch (HttpRequestException) //Skin not found? Reset to default icon + { + RevertToMCCIcon(); + } + finally + { + httpClient.Dispose(); + } } - )); - t.Name = "Player skin icon setter"; + )) + { + Name = "Player skin icon setter" + }; t.Start(); - } } /// /// Set the icon back to the default MCC icon /// - public static void revertToMCCIcon() + public static void RevertToMCCIcon() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) //Windows Only { try { - Icon defaultIcon = Icon.ExtractAssociatedIcon(System.Reflection.Assembly.GetExecutingAssembly().Location); + Icon defaultIcon = Icon.ExtractAssociatedIcon(Environment.ProcessPath!)!; SetWindowIcon(Icon.FromHandle(defaultIcon.Handle)); // Windows 10+ (New console) SetConsoleIcon(defaultIcon.Handle); // Windows 8 and lower (Older console) } diff --git a/MinecraftClient/WinAPI/ExitCleanUp.cs b/MinecraftClient/WinAPI/ExitCleanUp.cs index c3a62f8e..1de9864f 100644 --- a/MinecraftClient/WinAPI/ExitCleanUp.cs +++ b/MinecraftClient/WinAPI/ExitCleanUp.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Runtime.InteropServices; namespace MinecraftClient.WinAPI @@ -17,7 +15,7 @@ namespace MinecraftClient.WinAPI /// /// Store codes to run before quitting /// - private static List actions = new List(); + private static readonly List actions = new(); static ExitCleanUp() { @@ -31,10 +29,12 @@ namespace MinecraftClient.WinAPI catch (DllNotFoundException) { // Probably on mono, fallback to ctrl+c only - Console.CancelKeyPress += delegate (object sender, ConsoleCancelEventArgs e) + static void value(object sender, ConsoleCancelEventArgs e) { RunCleanUp(); - }; + } + + Console.CancelKeyPress += value!; } } @@ -81,7 +81,7 @@ namespace MinecraftClient.WinAPI [DllImport("Kernel32")] private static extern bool SetConsoleCtrlHandler(ConsoleCtrlHandler handler, bool add); private delegate bool ConsoleCtrlHandler(CtrlType sig); - private static ConsoleCtrlHandler _handler; + private static readonly ConsoleCtrlHandler? _handler; enum CtrlType { diff --git a/MinecraftClient/WinAPI/WindowsVersion.cs b/MinecraftClient/WinAPI/WindowsVersion.cs index b8fa09f2..3b4e94c6 100644 --- a/MinecraftClient/WinAPI/WindowsVersion.cs +++ b/MinecraftClient/WinAPI/WindowsVersion.cs @@ -22,25 +22,20 @@ namespace MinecraftClient.WinAPI { get { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - dynamic major; // The 'CurrentMajorVersionNumber' string value in the CurrentVersion key is new for Windows 10, // and will most likely (hopefully) be there for some time before MS decides to change this - again... - if (TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", out major)) - { - return (uint) major; - } + if (TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMajorVersionNumber", out dynamic? major)) + return (uint)major; // When the 'CurrentMajorVersionNumber' value is not present we fallback to reading the previous key used for this: 'CurrentVersion' - dynamic version; - if (!TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentVersion", out version)) + if (!TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentVersion", out dynamic? version)) return 0; - var versionParts = ((string) version).Split('.'); + var versionParts = ((string)version!).Split('.'); if (versionParts.Length != 2) return 0; - uint majorAsUInt; - return uint.TryParse(versionParts[0], out majorAsUInt) ? majorAsUInt : 0; + return uint.TryParse(versionParts[0], out uint majorAsUInt) ? majorAsUInt : 0; } return 0; @@ -54,25 +49,20 @@ namespace MinecraftClient.WinAPI { get { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - dynamic minor; // The 'CurrentMinorVersionNumber' string value in the CurrentVersion key is new for Windows 10, // and will most likely (hopefully) be there for some time before MS decides to change this - again... - if (TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMinorVersionNumber", out minor)) - { - return (uint) minor; - } + if (TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentMinorVersionNumber", out dynamic? minor)) + return (uint)minor; // When the 'CurrentMinorVersionNumber' value is not present we fallback to reading the previous key used for this: 'CurrentVersion' - dynamic version; - if (!TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentVersion", out version)) + if (!TryGetRegistryKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentVersion", out dynamic? version)) return 0; - var versionParts = ((string) version).Split('.'); + var versionParts = ((string)version!).Split('.'); if (versionParts.Length != 2) return 0; - uint minorAsUInt; - return uint.TryParse(versionParts[1], out minorAsUInt) ? minorAsUInt : 0; + return uint.TryParse(versionParts[1], out uint minorAsUInt) ? minorAsUInt : 0; } return 0; @@ -86,18 +76,20 @@ namespace MinecraftClient.WinAPI /// Key /// Value (output) /// TRUE if successfully retrieved - private static bool TryGetRegistryKey(string path, string key, out dynamic value) + private static bool TryGetRegistryKey(string path, string key, out dynamic? value) { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { value = null; - try { + try + { var rk = Registry.LocalMachine.OpenSubKey(path); if (rk == null) return false; value = rk.GetValue(key); return value != null; } - catch { + catch + { return false; } }