diff --git a/src/AndroidFileChooserBinding/AndroidFileChooserBinding.csproj b/src/AndroidFileChooserBinding/AndroidFileChooserBinding.csproj index 737d4c18..5c0af83e 100644 --- a/src/AndroidFileChooserBinding/AndroidFileChooserBinding.csproj +++ b/src/AndroidFileChooserBinding/AndroidFileChooserBinding.csproj @@ -10,6 +10,7 @@ AndroidFileChooserBinding AndroidFileChooserBinding 512 + v5.0 true diff --git a/src/AndroidFileChooserBinding/packages.config b/src/AndroidFileChooserBinding/packages.config index 6ad15f1b..8cdf15fa 100644 --- a/src/AndroidFileChooserBinding/packages.config +++ b/src/AndroidFileChooserBinding/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/src/App1/Resources/menu/group.xml b/src/App1/Resources/menu/group.xml new file mode 100644 index 00000000..43ceeb6b --- /dev/null +++ b/src/App1/Resources/menu/group.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/src/App1/Resources/xml/searchable_app1.xml b/src/App1/Resources/xml/searchable_app1.xml new file mode 100644 index 00000000..700b1a59 --- /dev/null +++ b/src/App1/Resources/xml/searchable_app1.xml @@ -0,0 +1,14 @@ + + + diff --git a/src/JavaFileStorageBindings/JavaFileStorageBindings.csproj b/src/JavaFileStorageBindings/JavaFileStorageBindings.csproj index d96be630..9d3e3e8a 100644 --- a/src/JavaFileStorageBindings/JavaFileStorageBindings.csproj +++ b/src/JavaFileStorageBindings/JavaFileStorageBindings.csproj @@ -10,6 +10,8 @@ JavaFileStorageBindings JavaFileStorageBindings 512 + True + v5.0 true diff --git a/src/KP2AKdbLibraryBinding/KP2AKdbLibraryBinding.csproj b/src/KP2AKdbLibraryBinding/KP2AKdbLibraryBinding.csproj index 74b84473..20ff6272 100644 --- a/src/KP2AKdbLibraryBinding/KP2AKdbLibraryBinding.csproj +++ b/src/KP2AKdbLibraryBinding/KP2AKdbLibraryBinding.csproj @@ -10,6 +10,7 @@ KP2AKdbLibraryBinding KP2AKdbLibraryBinding 512 + v5.0 true diff --git a/src/KeePass.sln b/src/KeePass.sln index 1f843e61..890c5bc0 100644 --- a/src/KeePass.sln +++ b/src/KeePass.sln @@ -36,6 +36,7 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MasterKeePlugin", "MasterKeePlugin\MasterKeePlugin.csproj", "{9A4C5BAA-1A8A-49B4-BBC3-60D4871FB36C}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MaterialTest2", "MaterialTest2\MaterialTest2.csproj", "{B7BBC4A2-0301-4DFF-B03C-C88CD4F1F890}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZlibAndroid", "ZlibAndroid\ZlibAndroid.csproj", "{6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -231,6 +232,30 @@ Global {5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU {5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU {5CF675A5-9BEE-4720-BED9-D5BF14A2EBF9}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.Debug|Win32.ActiveCfg = Debug|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.Debug|Win32.Build.0 = Debug|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.Debug|x64.ActiveCfg = Debug|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.Debug|x64.Build.0 = Debug|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.Release|Any CPU.Build.0 = Release|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.Release|Win32.ActiveCfg = Release|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.Release|Win32.Build.0 = Release|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.Release|x64.ActiveCfg = Release|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.Release|x64.Build.0 = Release|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|Win32.Build.0 = Release|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB}.ReleaseNoNet|x64.Build.0 = Release|Any CPU {70D3844A-D9FA-4A64-B205-A84C6A822196}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {70D3844A-D9FA-4A64-B205-A84C6A822196}.Debug|Any CPU.Build.0 = Debug|Any CPU {70D3844A-D9FA-4A64-B205-A84C6A822196}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU diff --git a/src/KeePassLib2Android/KeePassLib2Android.csproj b/src/KeePassLib2Android/KeePassLib2Android.csproj index f70ba567..3193bde6 100644 --- a/src/KeePassLib2Android/KeePassLib2Android.csproj +++ b/src/KeePassLib2Android/KeePassLib2Android.csproj @@ -12,7 +12,8 @@ Resources\Resource.designer.cs Resource KeePassLib2Android - v4.0.3 + v5.0 + True True @@ -156,6 +157,10 @@ {70D3844A-D9FA-4A64-B205-A84C6A822196} KP2AKdbLibraryBinding + + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB} + ZlibAndroid + \ No newline at end of file diff --git a/src/KeePassLib2Android/Serialization/KdbxFile.Read.cs b/src/KeePassLib2Android/Serialization/KdbxFile.Read.cs index d5d82fab..46477729 100644 --- a/src/KeePassLib2Android/Serialization/KdbxFile.Read.cs +++ b/src/KeePassLib2Android/Serialization/KdbxFile.Read.cs @@ -114,7 +114,7 @@ namespace KeePassLib.Serialization !m_bRepairMode); if(m_pwDatabase.Compression == PwCompressionAlgorithm.GZip) - readerStream = new GZipStream(sHashed, CompressionMode.Decompress); + readerStream = new Ionic.Zlib.GZipStream(sHashed, Ionic.Zlib.CompressionMode.Decompress); else readerStream = sHashed; } else if(kdbFormat == KdbxFormat.PlainXml) diff --git a/src/KeePassLib2Android/Serialization/KdbxFile.Write.cs b/src/KeePassLib2Android/Serialization/KdbxFile.Write.cs index a61e9bef..c601f3c9 100644 --- a/src/KeePassLib2Android/Serialization/KdbxFile.Write.cs +++ b/src/KeePassLib2Android/Serialization/KdbxFile.Write.cs @@ -115,7 +115,7 @@ namespace KeePassLib.Serialization Stream sHashed = new HashedBlockStream(sEncrypted, true); if(m_pwDatabase.Compression == PwCompressionAlgorithm.GZip) - writerStream = new GZipStream(sHashed, CompressionMode.Compress); + writerStream = new Ionic.Zlib.GZipStream(sHashed, Ionic.Zlib.CompressionMode.Compress); else writerStream = sHashed; } diff --git a/src/KeePassLib2Android/Translation/KPTranslation.cs b/src/KeePassLib2Android/Translation/KPTranslation.cs index 32b01089..27a5987c 100644 --- a/src/KeePassLib2Android/Translation/KPTranslation.cs +++ b/src/KeePassLib2Android/Translation/KPTranslation.cs @@ -103,7 +103,7 @@ namespace KeePassLib.Translation FileAccess.Write, FileShare.None); #if !KeePassLibSD - GZipStream gz = new GZipStream(fs, CompressionMode.Compress); + Ionic.Zlib.GZipStream gz = new Ionic.Zlib.GZipStream(fs, Ionic.Zlib.CompressionMode.Compress); #else GZipOutputStream gz = new GZipOutputStream(fs); #endif @@ -132,7 +132,7 @@ namespace KeePassLib.Translation FileAccess.Read, FileShare.Read); #if !KeePassLibSD - GZipStream gz = new GZipStream(fs, CompressionMode.Decompress); + Ionic.Zlib.GZipStream gz = new Ionic.Zlib.GZipStream(fs, Ionic.Zlib.CompressionMode.Decompress); #else GZipInputStream gz = new GZipInputStream(fs); #endif diff --git a/src/KeePassLib2Android/Utility/AppLogEx.cs b/src/KeePassLib2Android/Utility/AppLogEx.cs index ae16f699..25e50edc 100644 --- a/src/KeePassLib2Android/Utility/AppLogEx.cs +++ b/src/KeePassLib2Android/Utility/AppLogEx.cs @@ -68,7 +68,7 @@ namespace KeePassLib.Utility FileStream fsOut = new FileStream(strPath, FileMode.Create, FileAccess.Write, FileShare.None); - GZipStream gz = new GZipStream(fsOut, CompressionMode.Compress); + Ionic.Zlib.GZipStream gz = new Ionic.Zlib.GZipStream(fsOut, CompressionMode.Compress); m_swOut = new StreamWriter(gz); AppLogEx.Log("Started logging on " + dtNow.ToString("s") + "."); diff --git a/src/KeePassLib2Android/Utility/MemUtil.cs b/src/KeePassLib2Android/Utility/MemUtil.cs index 8c2e937b..a5b10e47 100644 --- a/src/KeePassLib2Android/Utility/MemUtil.cs +++ b/src/KeePassLib2Android/Utility/MemUtil.cs @@ -430,7 +430,7 @@ namespace KeePassLib.Utility if(pbData.Length == 0) return pbData; MemoryStream msCompressed = new MemoryStream(); - GZipStream gz = new GZipStream(msCompressed, CompressionMode.Compress); + Ionic.Zlib.GZipStream gz = new Ionic.Zlib.GZipStream(msCompressed, Ionic.Zlib.CompressionMode.Compress); MemoryStream msSource = new MemoryStream(pbData, false); MemUtil.CopyStream(msSource, gz); gz.Close(); @@ -447,7 +447,7 @@ namespace KeePassLib.Utility if(pbCompressed.Length == 0) return pbCompressed; MemoryStream msCompressed = new MemoryStream(pbCompressed, false); - GZipStream gz = new GZipStream(msCompressed, CompressionMode.Decompress); + Ionic.Zlib.GZipStream gz = new Ionic.Zlib.GZipStream(msCompressed, Ionic.Zlib.CompressionMode.Decompress); MemoryStream msData = new MemoryStream(); MemUtil.CopyStream(gz, msData); gz.Close(); diff --git a/src/Kp2aBusinessLogic/Io/DropboxFileStorageKeysDummy.cs b/src/Kp2aBusinessLogic/Io/DropboxFileStorageKeysDummy.cs new file mode 100644 index 00000000..70c1310a --- /dev/null +++ b/src/Kp2aBusinessLogic/Io/DropboxFileStorageKeysDummy.cs @@ -0,0 +1,13 @@ +namespace keepass2android.Io +{ + public partial class DropboxFileStorage + { + private const string AppKey = ""; + private const string AppSecret = ""; + } + public partial class DropboxAppFolderFileStorage + { + private const string AppKey = ""; + private const string AppSecret = ""; + } +} \ No newline at end of file diff --git a/src/Kp2aKeyboardBinding/Kp2aKeyboardBinding.csproj b/src/Kp2aKeyboardBinding/Kp2aKeyboardBinding.csproj index c5585dbd..8c08fbcb 100644 --- a/src/Kp2aKeyboardBinding/Kp2aKeyboardBinding.csproj +++ b/src/Kp2aKeyboardBinding/Kp2aKeyboardBinding.csproj @@ -10,6 +10,8 @@ Assets Resources Kp2aKeyboardBinding + True + v5.0 True diff --git a/src/PluginSdkBinding/PluginSdkBinding.csproj b/src/PluginSdkBinding/PluginSdkBinding.csproj index ba721def..ae961f12 100644 --- a/src/PluginSdkBinding/PluginSdkBinding.csproj +++ b/src/PluginSdkBinding/PluginSdkBinding.csproj @@ -10,6 +10,8 @@ PluginSdkBinding PluginSdkBinding 512 + True + v5.0 true diff --git a/src/TwofishCipher/TwofishCipher.csproj b/src/TwofishCipher/TwofishCipher.csproj index a031a7b0..b7ef6e40 100644 --- a/src/TwofishCipher/TwofishCipher.csproj +++ b/src/TwofishCipher/TwofishCipher.csproj @@ -12,6 +12,8 @@ 512 Resources\Resource.Designer.cs Off + True + v5.0 true diff --git a/src/ZlibAndroid/CRC32.cs b/src/ZlibAndroid/CRC32.cs new file mode 100644 index 00000000..53a4fa37 --- /dev/null +++ b/src/ZlibAndroid/CRC32.cs @@ -0,0 +1,814 @@ +// 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/src/ZlibAndroid/Deflate.cs b/src/ZlibAndroid/Deflate.cs new file mode 100644 index 00000000..be401b8d --- /dev/null +++ b/src/ZlibAndroid/Deflate.cs @@ -0,0 +1,1879 @@ +// 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/src/ZlibAndroid/DeflateStream.cs b/src/ZlibAndroid/DeflateStream.cs new file mode 100644 index 00000000..45e972b2 --- /dev/null +++ b/src/ZlibAndroid/DeflateStream.cs @@ -0,0 +1,740 @@ +// 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/src/ZlibAndroid/GZipStream.cs b/src/ZlibAndroid/GZipStream.cs new file mode 100644 index 00000000..f83ccddc --- /dev/null +++ b/src/ZlibAndroid/GZipStream.cs @@ -0,0 +1,1033 @@ +// 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/src/ZlibAndroid/InfTree.cs b/src/ZlibAndroid/InfTree.cs new file mode 100644 index 00000000..ffc5bb6f --- /dev/null +++ b/src/ZlibAndroid/InfTree.cs @@ -0,0 +1,436 @@ +// 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; +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. + + 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/src/ZlibAndroid/Resources/AboutResources.txt b/src/ZlibAndroid/Resources/AboutResources.txt new file mode 100644 index 00000000..54c2267a --- /dev/null +++ b/src/ZlibAndroid/Resources/AboutResources.txt @@ -0,0 +1,44 @@ +Images, layout descriptions, binary blobs and string dictionaries can be included +in your application as resource files. Various Android APIs are designed to +operate on the resource IDs instead of dealing with images, strings or binary blobs +directly. + +For example, a sample Android app that contains a user interface layout (main.axml), +an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) +would keep its resources in the "Resources" directory of the application: + +Resources/ + drawable/ + icon.png + + layout/ + main.axml + + values/ + strings.xml + +In order to get the build system to recognize Android resources, set the build action to +"AndroidResource". The native Android APIs do not operate directly with filenames, but +instead operate on resource IDs. When you compile an Android application that uses resources, +the build system will package the resources for distribution and generate a class called "R" +(this is an Android convention) that contains the tokens for each one of the resources +included. For example, for the above Resources layout, this is what the R class would expose: + +public class R { + public class drawable { + public const int icon = 0x123; + } + + public class layout { + public const int main = 0x456; + } + + public class strings { + public const int first_string = 0xabc; + public const int second_string = 0xbcd; + } +} + +You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main +to reference the layout/main.axml file, or R.strings.first_string to reference the first +string in the dictionary file values/strings.xml. diff --git a/src/ZlibAndroid/Resources/values/Strings.xml b/src/ZlibAndroid/Resources/values/Strings.xml new file mode 100644 index 00000000..8d16a887 --- /dev/null +++ b/src/ZlibAndroid/Resources/values/Strings.xml @@ -0,0 +1,4 @@ + + + ZlibAndroid + diff --git a/src/ZlibAndroid/Tree.cs b/src/ZlibAndroid/Tree.cs new file mode 100644 index 00000000..954872aa --- /dev/null +++ b/src/ZlibAndroid/Tree.cs @@ -0,0 +1,423 @@ +// 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/src/ZlibAndroid/Zlib.cs b/src/ZlibAndroid/Zlib.cs new file mode 100644 index 00000000..6c51b1aa --- /dev/null +++ b/src/ZlibAndroid/Zlib.cs @@ -0,0 +1,546 @@ +// 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 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); + /// + /// + 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/src/ZlibAndroid/ZlibAndroid.csproj b/src/ZlibAndroid/ZlibAndroid.csproj new file mode 100644 index 00000000..682a54e3 --- /dev/null +++ b/src/ZlibAndroid/ZlibAndroid.csproj @@ -0,0 +1,66 @@ + + + + Debug + AnyCPU + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {6C29A7E7-E016-4FC1-B1A0-DEE26AC711BB} + Library + ZlibAndroid + Resources\Resource.designer.cs + Resource + Resources + Assets + True + ZlibAndroid + v5.0 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + None + + + full + true + bin\Release + prompt + 4 + false + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ZlibAndroid/ZlibBaseStream.cs b/src/ZlibAndroid/ZlibBaseStream.cs new file mode 100644 index 00000000..8243eeca --- /dev/null +++ b/src/ZlibAndroid/ZlibBaseStream.cs @@ -0,0 +1,627 @@ +// 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; + +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/src/ZlibAndroid/ZlibCodec.cs b/src/ZlibAndroid/ZlibCodec.cs new file mode 100644 index 00000000..813d2481 --- /dev/null +++ b/src/ZlibAndroid/ZlibCodec.cs @@ -0,0 +1,717 @@ +// 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 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!"); + // TODO: 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/src/ZlibAndroid/ZlibConstants.cs b/src/ZlibAndroid/ZlibConstants.cs new file mode 100644 index 00000000..7952ce20 --- /dev/null +++ b/src/ZlibAndroid/ZlibConstants.cs @@ -0,0 +1,128 @@ +// 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/src/ZlibAndroid/ZlibStream.cs b/src/ZlibAndroid/ZlibStream.cs new file mode 100644 index 00000000..57b308c0 --- /dev/null +++ b/src/ZlibAndroid/ZlibStream.cs @@ -0,0 +1,725 @@ +// 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; + +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/src/java/KP2ASoftKeyboard2/java/res/values-bg-rBG/strings_kp2a.xml b/src/java/KP2ASoftKeyboard2/java/res/values-bg-rBG/strings_kp2a.xml index e7336b61..b5d5f436 100644 --- a/src/java/KP2ASoftKeyboard2/java/res/values-bg-rBG/strings_kp2a.xml +++ b/src/java/KP2ASoftKeyboard2/java/res/values-bg-rBG/strings_kp2a.xml @@ -1,10 +1,20 @@ - + Изберете друг запис - Изберете + Изберете стойност Търсене за въведено с \"%1$s\" Потребител Парола - Автоматично попълване разрешено + Входни настройки на данни + Автоматично попълване е включено + Автоматично попълване при въведено празно поле, ако е Keepass2Android запис е на разположение за клавиатурата и има стойност, която съответства на полето на подсказване. + Запомни скрития текст в полето + Ако текстово поле е попълнено чрез ръчно избиране на стойност от Keepass2Android, запомни коя стойност е въведена в текстовото поле. Полето по-късно ще бъде сравнено със скритата стойност. + Проста клавиатура + Покажи простата 1 редова клавиатура ако стойноста е налична. Ако е изключена се показва диалог при натискане на бутон на Keepass2Android + Заключване на базата данни, когато е готово + При натискане на клавиша Done/Send/Go на простата 1-редова клавиатура, автоматично се заключва на базата данни. + Превключване на клавиатурата, когато свършиш + При натискане на клавиша Done/Send/Go на простата 1-редова клавиатура, превключи клавиатурата. diff --git a/src/java/KP2ASoftKeyboard2/java/res/values-fr/strings_kp2a.xml b/src/java/KP2ASoftKeyboard2/java/res/values-fr/strings_kp2a.xml index 429c4c43..868b991a 100644 --- a/src/java/KP2ASoftKeyboard2/java/res/values-fr/strings_kp2a.xml +++ b/src/java/KP2ASoftKeyboard2/java/res/values-fr/strings_kp2a.xml @@ -6,7 +6,7 @@ Rechercher une entrée avec \"%1$s\" Utilisateur Mot de passe - Paramètres d\'entrée des informations d\'identification + Paramètres d\'entrée des identifiants Remplissage automatique activé Renseigner automatiquement le texte lorsqu\'un champ vide est saisi, si une entrée Keepass2Android est disponible pour le clavier et qu\'il y a un champ qui correspond au texte d\'indication du champ. Rappeler le texte du champ d\'information diff --git a/src/java/KP2ASoftKeyboard2/java/res/values-nb/strings_kp2a.xml b/src/java/KP2ASoftKeyboard2/java/res/values-nb/strings_kp2a.xml index 6321b63a..ef6df9b9 100644 --- a/src/java/KP2ASoftKeyboard2/java/res/values-nb/strings_kp2a.xml +++ b/src/java/KP2ASoftKeyboard2/java/res/values-nb/strings_kp2a.xml @@ -6,9 +6,15 @@ Søke etter oppføringen med \"%1$s\" Bruker Passord + Innstillinger for innloggingsdetaljer Autofyll aktivert + Fyll inn tomme felter automatisk dersom det fins en oppføring for tastaturet til Keepass2Android, og det fins en verdi som samsvarer med feltets hinttekst. + Husk feltenes hinttekster + Dersom feltet fylles manuelt ved å velge en verdi fra Keepass2Android, husk verdien som ble skrevet inn i tekstfeltet. Tekstfeltet vil senere bli gjenkjent av dets hinttekst. Enkelt tastatur Vis det enkle 1 rad tastaturet hvis det finnes en oppføring for tastaturet. Hvis deaktivert, vises en dialogboks når Keepass2Android tasten trykkes. Lås databasen når ferdig + Når du trykker tasten for Ferdig/Send/Gå på det enkle enlinjers tastturet, lås databasen automatisk. Bytt tastatur når ferdig + Når du trykker tasten for Ferdig/Send/Gå på det enkle enlinjers tastturet, bytt tastatur. diff --git a/src/java/KP2ASoftKeyboard2/java/res/values-pt-rPT/strings_kp2a.xml b/src/java/KP2ASoftKeyboard2/java/res/values-pt-rPT/strings_kp2a.xml index 6a07316e..ac6ee4fd 100644 --- a/src/java/KP2ASoftKeyboard2/java/res/values-pt-rPT/strings_kp2a.xml +++ b/src/java/KP2ASoftKeyboard2/java/res/values-pt-rPT/strings_kp2a.xml @@ -12,6 +12,9 @@ Lembrar os textos de dica de campo Se um campo de texto é preenchido manualmente selecionando o valor de Keepass2Android, lembra-se de qual valor foi inserido no campo de texto. O campo de texto mais tarde é detectado novamente pelo seu texto de dica. Teclado simples + Mostrar teclado simples de 1 linha se existir uma entrada disponível para o teclado. Se desactivado, uma caixa de diálogo é mostrada quando é pressionada a tecla Keepass2Android. Bloquear base de dados no final + Ao pressionar a tecla Concluido/Enviar/Ir no teclado de 1 linha simples, bloquear a base de dados automaticamente. Trocar teclado ao concluir + Ao pressionar a tecla Concluido/Enviar/Ir no teclado de 1 linha simples, trocar o teclado. diff --git a/src/java/KP2ASoftKeyboard2/java/res/values-ro/strings_kp2a.xml b/src/java/KP2ASoftKeyboard2/java/res/values-ro/strings_kp2a.xml index 7cc1daf3..df9110c5 100644 --- a/src/java/KP2ASoftKeyboard2/java/res/values-ro/strings_kp2a.xml +++ b/src/java/KP2ASoftKeyboard2/java/res/values-ro/strings_kp2a.xml @@ -2,7 +2,19 @@ Selectaţi o altă înregistrare - Alegeți înregistraea + Alegeți înregistrarea Căutaţi înregistrarea \"%1$s\" - Dacă un câmp text este completat prin selectarea manual valoarea Keepass2Android, memoreaza valoarea care a intrat în câmpul de text. Câmpul de text este redetectat mai târziu de textul său de sugestie. + Utilizator + Parolă + Setări pentru introducerea datelor + Completarea-auto activată + Completează automat când un câmp gol este selectat, dacă o înregistrare Keepass2Android este disponibilă pentru tastatură și există o valoare care corespunde textului sugestie al câmpului. + Memorează textul de sugestie al câmpurilor + Dacă un câmp text este completat prin selectarea manuală a valorii Keepass2Android, memorează valoarea care era introdusă în câmpul de text. Câmpul de text este redetectat mai târziu de textul său de sugestie. + Tastatură simplă + Arată tastatura simplă de un rând dacă o înregistrare este disponibilă pentru tastatură. Dacă este dezactivat, se afișează un dialog când tasta Keepass2Android este apăsată. + Blochează baza de date când ai terminat + Când apeși tasta Done/Send/Go de pe tastatura simplă de un rând, blochează automat baza de date. + Comută tastatura când ai terminat + După ce ai apăsat tasta Gata/Trimite/Mergi de pe tastatura simplă cu un rând, comută tastatura. diff --git a/src/java/KP2ASoftKeyboard2/java/res/values-sl/strings_kp2a.xml b/src/java/KP2ASoftKeyboard2/java/res/values-sl/strings_kp2a.xml index 0fb28b48..c40545a9 100644 --- a/src/java/KP2ASoftKeyboard2/java/res/values-sl/strings_kp2a.xml +++ b/src/java/KP2ASoftKeyboard2/java/res/values-sl/strings_kp2a.xml @@ -1,3 +1,20 @@ - + + Izberite drug vnos + Izberite vnos + Poišči vnos s/z \"%1$s\" + Uporabnik + Geslo + Nastavitve za vnos poveril + Samodejno izpolnjevanje omogočeno + Samodejno izpolni besedilo, ko izbrano prazno polje, če je za tipkovnico na voljo vnos Keepass2Android in obstaja vrednost, ki se ujema z besedilom namiga polja. + Zapomni si besedila namigov polj + Če je besedilo izpolnjeno z ročno izbiro vrednosti Keepass2Android, si zapomni, katera vrednost je bila vnesena v besedilno polje. To polje kasneje ponovno zazna njegovo besedilo namiga. + Preprosta tipkovnica + Prikaži preprosto enovrstično tipkovnico, če je za tipkovnico vnos na voljo vnos. Če je onemogočeno, se ob pritisku na tipko Keepass2Android prikaže pogovorno okno. + Zakleni podatkovno zbirko, ko je končano + Ob pritisku na tipko Končano/Pošlji/Pojdi na preprosti enovrstični tipkovnici samodejno zakleni podatkovno zbirko. + Preklopi tipkovnico, ko je končano + Ob pritisku na tipko Končano/Pošlji/Pojdi na preprosti enovrstični tipkovnici preklopi tipkovnico. + diff --git a/src/java/KP2ASoftKeyboard2/java/res/values-zh-rTW/strings_kp2a.xml b/src/java/KP2ASoftKeyboard2/java/res/values-zh-rTW/strings_kp2a.xml index 5cabadba..35a96a96 100644 --- a/src/java/KP2ASoftKeyboard2/java/res/values-zh-rTW/strings_kp2a.xml +++ b/src/java/KP2ASoftKeyboard2/java/res/values-zh-rTW/strings_kp2a.xml @@ -8,4 +8,6 @@ 密碼 憑據輸入設置 自動輸入啟用 + 當選擇空白欄位時,如果有可使用的 Keepass2Android 條目以及當網站符合條目資訊時將自動填入資料。 + 記住欄位提示訊息 diff --git a/src/java/android-filechooser/code/res/values-bg-rBG/strings.xml b/src/java/android-filechooser/code/res/values-bg-rBG/strings.xml index 1d81a123..34f08982 100644 --- a/src/java/android-filechooser/code/res/values-bg-rBG/strings.xml +++ b/src/java/android-filechooser/code/res/values-bg-rBG/strings.xml @@ -1,5 +1,5 @@ - + - + + Alle + Invertere valg + Ingen + Rutenettvisning + Hjem + Listevisning + Ny mappe… + Velg alle filer + Velg alle mapper + Sorter… + filen + mappen + tøm + mappenavn + filnavn + søk + Dette programmet har ikke tillatelse til å opprette filer/mapper + Dette programmet har ikke tillatelse til å slette filer/mapper + Avbrutt + Kan ikke koble til filleveringstjenesten + Kan ikke opprette mappe her + Kan ikke lagre fil her + Ferdig + Tom + Mislyktes. Vennligst prøv igjen. + Laster… + Telefon + Får ikke tilgang til \"%1$s\" + Kan ikke opprette mappen \"%1$s\" + Kan ikke slette %1$s \"%2$s\" + Er du sikker på at du ønsker å slette denne %1$s \"%2$s\"? + Filen \"%1$s\" fins allerede.\n\nVil du erstatte den? + Sletter %1$s \"%2$s\"… + %1$s \"%2$s\" er slettet + \"%1$s\" er en mappe + Filnavnet \"%1$s\" er ugyldig + …har flere filer, maks tillatt: %1$,d + Ukjent feil: %1$s + Toppnivå + Velg… + Bekreftelse + Dato + Feil + Info + Navn + Lagre som… + Størrelse + Sorter etter… + I går + + Velg mappe… + Velg mapper… + + + Velg fil… + Velg filer… + + + Velg fil/mappe… + Velg filer/mapper… + + diff --git a/src/java/android-filechooser/code/res/values-ro/strings.xml b/src/java/android-filechooser/code/res/values-ro/strings.xml index f47b821d..b0c03f8d 100644 --- a/src/java/android-filechooser/code/res/values-ro/strings.xml +++ b/src/java/android-filechooser/code/res/values-ro/strings.xml @@ -12,38 +12,38 @@ Nici unul Vizualizare grilă Acasă - Vedere lista + Vizualizare lista Director nou… Selectaţi toate fişierele - Selectaţi toate directoarele + Selectaţi toate folderele Sortare… fişier director goleşte - nume director - nume fisier + nume folder + nume fișier căutare - Această aplicaţie nu are permisiunea de a crea fişiere / directoare - Această aplicaţie nu are permisiunea de a şterge fişiere / directoare + Această aplicaţie nu are permisiunea de a crea fişiere / foldere + Această aplicaţie nu are permisiunea de a şterge fişiere / foldere Anulat - Conectare imposibila la furnizorul fisierului - Imposibil de creat dosarul nou aici + Conectare imposibilă la furnizorul fișierului + Imposibil de creat folder nou aici Imposibil de salvat un fişier aici Gata Gol Esec. Vă rugăm să încercaţi din nou. Se încarcă… Telefon - Nu pot accesa \"%1$s\" - Nu poate crea folderul \"%1$s\" + Nu se poate accesa \"%1$s\" + Nu se poate crea folderul \"%1$s\" Imposibil de şters %1$s \"%2$s\" - Sigur vreți sa ștergeți acest %1$s \"%2$s\"? - Acest fişier \"%1$s\" exista deja.\n\nDoriţi să-l înlocuiți? + Sigur vreți să ștergeți acest %1$s \"%2$s\"? + Acest fişier \"%1$s\" există deja.\n\nDoriţi să-l înlocuiți? Ştergere %1$s \"%2$s\"… %1$s \"%2$s\" a fost şters \"%1$s\" este un dosar Numele de fişier \"%1$s\" este invalid - … are prea multe fişiere, maximum permis: %1$, d + … are prea multe fişiere, maximum permis: %1$,d Eroare necunoscută: %1$s Root Selectaţi… diff --git a/src/java/android-filechooser/code/res/values-sl/strings.xml b/src/java/android-filechooser/code/res/values-sl/strings.xml index f72e232f..0da1ab5c 100644 --- a/src/java/android-filechooser/code/res/values-sl/strings.xml +++ b/src/java/android-filechooser/code/res/values-sl/strings.xml @@ -6,4 +6,72 @@ See the file LICENSE at the root directory of this project for copying permission. --> - + + Vse + Obrni izbiro + Brez + Mrežni pogled + Domov + Pogled seznama + Nova mapa … + Izberi vse datoteke + Izberi vse mape + Razvrsti … + datoteke + mape + počisti + ime mape + ime datoteke + išči + Ta program nima dovoljenja za ustvarjanje datotek/map + Ta program nima dovoljenja za izbris datotek/map + Preklicano + Povezava na storitev ponudnika datotek ni mogoča + Ustvarjanje mape na tem mestu ni mogoče + Shranjevanje datoteke na tem mestu ni mogoče + Končano + Prazno + Spodletelo. Poizkusite znova. + Nalaganje … + Telefon + Dostop do \"%1$s\" ni mogoč + Ustvarjanje mape \"%1$s\" ni mogoče + Izbris %1$s \"%2$s\" ni mogoč + Ali res želite izbrisati to %1$s \"%2$s\"? + Ta datoteka \"%1$s\" že obstaja.\n\nAli jo želite nadomestiti? + Brisanje %1$s \"%2$s\" … + %1$s \"%2$s\" je bila izbrisana + \"%1$s\" je mapa + Ime datoteke \"%1$s\" je neveljavno + … ima več datotek, največje dovoljeno št.: %1,d + Neznana napaka: %1$s + Koren + Izberite … + Potrditev + Datum + Napaka + Podatki + Ime + Shrani kot … + Velikost + Razvrsti po … + Včeraj + + Izberite mapo … + Izberite mapi … + Izberite mape … + Izberite mape … + + + Izberite datoteko … + Izberite datoteki … + Izberite datoteke … + Izberite datoteke … + + + Izberite datoteko/mapo … + Izberite datoteki/mapi … + Izberite datoteke/mape … + Izberite datoteke/mape … + + diff --git a/src/keepass2android/AboutActivity.cs b/src/keepass2android/AboutActivity.cs index dc8ddb3b..03ebc70a 100644 --- a/src/keepass2android/AboutActivity.cs +++ b/src/keepass2android/AboutActivity.cs @@ -10,7 +10,7 @@ namespace keepass2android { [Activity(Label = "@string/app_name", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden, - Theme = "@style/MyTheme_ActionBar")] + Theme = "@style/MyTheme_ActionBar")] [IntentFilter(new[] { "keepass2android.AboutActivity" }, Categories = new[] { Intent.CategoryDefault })] public class AboutActivity: Activity, IDialogInterfaceOnDismissListener { diff --git a/src/keepass2android/ChangeLog.cs b/src/keepass2android/ChangeLog.cs index 29c99f43..0fe79bca 100644 --- a/src/keepass2android/ChangeLog.cs +++ b/src/keepass2android/ChangeLog.cs @@ -26,6 +26,7 @@ namespace keepass2android AlertDialog.Builder builder = new AlertDialog.Builder(new ContextThemeWrapper(ctx, Android.Resource.Style.ThemeHoloLightDialog)); builder.SetTitle(ctx.GetString(Resource.String.ChangeLog_title)); List changeLog = new List{ + ctx.GetString(Resource.String.ChangeLog_0_9_8b), ctx.GetString(Resource.String.ChangeLog_0_9_8), #if !NoNet //0.9.7b fixes were already included in 0.9.7 offline diff --git a/src/keepass2android/CreateDatabaseActivity.cs b/src/keepass2android/CreateDatabaseActivity.cs index 8e4200cd..bd04a99e 100644 --- a/src/keepass2android/CreateDatabaseActivity.cs +++ b/src/keepass2android/CreateDatabaseActivity.cs @@ -361,6 +361,7 @@ namespace keepass2android } if (requestCode == RequestCodeDbFilename) { + if (data.Data.Scheme == "content") { if ((int)Build.VERSION.SdkInt >= 19) diff --git a/src/keepass2android/DonateReminder.cs b/src/keepass2android/DonateReminder.cs index b00037f2..a80363fa 100644 --- a/src/keepass2android/DonateReminder.cs +++ b/src/keepass2android/DonateReminder.cs @@ -43,12 +43,34 @@ namespace keepass2android static IEnumerable GetReminders() { yield return new Reminder - { - From = new DateTime(2014, 09, 20), - To = new DateTime(2014, 10, 06), - Key = "DonationOktoberfest2014" + { + From = new DateTime(2015, 09, 19), + To = new DateTime(2015, 10, 05), + Key = "DonationOktoberfest2015" ,ResourceToShow = Resource.Layout.donate - }; + }; + + yield return new Reminder + { + From = new DateTime(2016, 09, 17), + To = new DateTime(2016, 10, 04), + Key = "DonationOktoberfest2016" + ,ResourceToShow = Resource.Layout.donate + }; + yield return new Reminder + { + From = new DateTime(2015, 09, 16), + To = new DateTime(2015, 10, 04), + Key = "DonationOktoberfest2017" + ,ResourceToShow = Resource.Layout.donate + }; + yield return new Reminder + { + From = new DateTime(2015, 09, 22), + To = new DateTime(2015, 10, 08), + Key = "DonationOktoberfest2018" + ,ResourceToShow = Resource.Layout.donate + }; int thisYear = DateTime.Now.Year; diff --git a/src/keepass2android/ExportDatabaseActivity.cs b/src/keepass2android/ExportDatabaseActivity.cs index b62e96f6..507598bf 100644 --- a/src/keepass2android/ExportDatabaseActivity.cs +++ b/src/keepass2android/ExportDatabaseActivity.cs @@ -17,7 +17,7 @@ namespace keepass2android [Activity(Label = "@string/app_name", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden, Theme = "@style/MyTheme_ActionBar")] - [IntentFilter(new[] {"keepass2android.ExportDatabaseActivity"}, Categories = new[] {Intent.CategoryDefault})] + [IntentFilter(new[] {"kp2a.action.ExportDatabaseActivity"}, Categories = new[] {Intent.CategoryDefault})] public class ExportDatabaseActivity : LockCloseActivity { FileFormatProvider[] _ffp = new FileFormatProvider[] @@ -56,6 +56,12 @@ namespace keepass2android if (resultCode == KeePass.ExitFileStorageSelectionOk) { string protocolId = data.GetStringExtra("protocolId"); + if (protocolId == "content") + { + Util.ShowBrowseDialog(this, RequestCodeDbFilename, true, true); + } + else + { App.Kp2a.GetFileStorage(protocolId).StartSelectFile(new FileStorageSetupInitiatorActivity(this, OnActivityResult, defaultPath => @@ -67,6 +73,7 @@ namespace keepass2android Intents.RequestCodeFileBrowseForOpen); } ), true, RequestCodeDbFilename, protocolId); + } return; } @@ -74,8 +81,33 @@ namespace keepass2android { if (requestCode == RequestCodeDbFilename) { - string filename = Util.IntentToFilename(data, this); + if (data.Data.Scheme == "content") + { + if ((int)Android.OS.Build.VERSION.SdkInt >= 19) + { + //try to take persistable permissions + try + { + Kp2aLog.Log("TakePersistableUriPermission"); + var takeFlags = data.Flags + & (ActivityFlags.GrantReadUriPermission + | ActivityFlags.GrantWriteUriPermission); + this.ContentResolver.TakePersistableUriPermission(data.Data, takeFlags); + } + catch (Exception e) + { + Kp2aLog.Log(e.ToString()); + } + + } + } + + + string filename = Util.IntentToFilename(data, this); + if (filename == null) + filename = data.DataString; + bool fileExists = data.GetBooleanExtra("group.pals.android.lib.ui.filechooser.FileChooserActivity.result_file_exists", true); if (fileExists) diff --git a/src/keepass2android/GroupActivity.cs b/src/keepass2android/GroupActivity.cs index 6ae4b4ff..e6c4448a 100644 --- a/src/keepass2android/GroupActivity.cs +++ b/src/keepass2android/GroupActivity.cs @@ -44,6 +44,8 @@ namespace keepass2android [IntentFilter(new[] { "android.intent.action.SEARCH" })] [MetaData("android.app.default_searchable", Value = "MaterialTest2.EntryEditActivity")] [MetaData("android.app.searchable", Resource = "@xml/searchable_mattest")] + [IntentFilter(new string[]{"android.intent.action.SEARCH"})] + [MetaData("android.app.searchable",Resource=AppNames.Searchable)] public class GroupActivity : GroupBaseActivity { public const int Uninit = -1; diff --git a/src/keepass2android/GroupBaseActivity.cs b/src/keepass2android/GroupBaseActivity.cs index 9ac06ffb..81649b88 100644 --- a/src/keepass2android/GroupBaseActivity.cs +++ b/src/keepass2android/GroupBaseActivity.cs @@ -397,12 +397,12 @@ namespace keepass2android MenuInflater inflater = MenuInflater; inflater.Inflate(Resource.Menu.group, menu); - var searchManager = (SearchManager) GetSystemService(SearchService); + var searchManager = (SearchManager)GetSystemService (Context.SearchService); IMenuItem searchItem = menu.FindItem(Resource.Id.menu_search); var view = MenuItemCompat.GetActionView(searchItem); var searchView = view.JavaCast(); - searchView.SetSearchableInfo(searchManager.GetSearchableInfo(ComponentName)); + searchView.SetSearchableInfo (searchManager.GetSearchableInfo (ComponentName)); searchView.SetOnSuggestionListener(new SuggestionListener(searchView.SuggestionsAdapter, this, searchItem)); searchView.SetOnQueryTextListener(new OnQueryTextListener(this)); diff --git a/src/keepass2android/Resources/values-bg-rBG/strings.xml b/src/keepass2android/Resources/values-bg-rBG/strings.xml index 9e0e135d..59d51513 100644 --- a/src/keepass2android/Resources/values-bg-rBG/strings.xml +++ b/src/keepass2android/Resources/values-bg-rBG/strings.xml @@ -6,7 +6,9 @@ Уеб страница Keepass2Android е мениджър за пароли който осигурява достъп четене/записване до KeePass 2.x база данни на Android. Потребителският интерфейс е базиран на KeepassDroid създаден от Brian Pellin. Кода действие на базите данни е базиран на KeePass на Dominik Reichl. Робота Android е репродукция или модифициран от разработения и споделен от Google и се използва в съответствие с лиценза Creative Commons 3.0 Attribution License. + SFTP поддръжка се осъществява чрез използване на библиотеката на JSch под BSD лиценз, създаден от JCraft, Inc. Приемам + Отказано Добавям запис Създавам запис от страница Добавям група @@ -25,6 +27,11 @@ Покажи бутон за спиране на приложението в екрана за парола (за параноични потребители) Приложение Настройки на приложението + Показване на името на групата в резултата от търсенето + Показване на името на групата под заглавието в резултатите от търсенето. Полезно е, ако няколко записа имат едно и също име. + Групата за показване е: %1$s + Покажи името на групата във вид на запис + Съжалявам! Keepass2Android не може да обработи върнатите URI %1$s. Свържете се с разработчика! Сигурност Покажи Достъп до въведените пароло @@ -32,6 +39,14 @@ Работа с файлове Клавиатура Експортиране на база данни... + Импортиране на БД във вътрешна папка + Импортирай ключ от вътрешна папка + Превключване на клавиатурата + Достъпно само за локални файлове. + Файлът се съхранява във вътрешна папка + База данни файлът е копиран във вътрешна папка. Натиснете Ok, за да отворите ново местоположение. Забележка: Не забравяйте редовно да експортирате базата данни на безопасно място + Keyfile е копиран във вътрешна папка. Уверете се, че имате бекъп преди да го изтриете от текущото му място! + Не можете да използвате вътрешна папка ако key файла не е запомнен. Променете настройките на сигурността. Скоби Прекъсни Клиброда е изчистен. @@ -40,6 +55,7 @@ Изберете за да копиране потребителското име в клипборда Изберете за да копирате парола в клипборда Въвеждането е възможно чрез KP2A клавиатурата + е наличен Невъзможно отваряне на диалог за избиране на метод за въвеждане. Моля активирайте клавиатурата ръчно. Моля активирайте клавиатурата на Keepass2Android във вашата системни настройки. Създаване на ключ на базата данни… @@ -49,6 +65,7 @@ Цифри Keepass2Android е с АБСОЛЮТНО НИКАКВИ ГАРАНЦИИ. Това е свободен софтуер и вие сте свободни да го разпространявате при условията на GPL врсия 2 и по-късни. \u2026 + Копиране в клипборда Въведете име на файла на базаданни Достъп до Отказ @@ -58,17 +75,42 @@ Потвърди паролата Създаден Изтича + Име на група Ключов файл (незадължителен) + Key файл Модифициран Парола Запази Име URL Потребителско име + Допълнителни низ полета Прикачени файлове + Keepass2Android не може да обработи този uri. Грешка при създаване на група. + Не може да се създаде директория. Този файл вече съществува. + Не можа да определи настройките на базата данни. + Неуспешно отваряне на линк. + Изисква се име на файл. + Не можа да създаде файл Невалидна база данни. + Невалиден път. + Името е задължително. + Изисква се парола или ключов файл. + Трябва да бъде избран поне един вид генератор за парола + Паролите не съвпадат. + Кръга трябва да бъде число. + Изисква се заглавие. + Въведете положително число в полето \"дължина\" + Файлът не е намерен. + Файл браузър + Генериране на парола + Група + коментар + Потвърди паролата + генерира парола + Име на група Ключов файл Дължина парола @@ -78,7 +120,11 @@ замени url таг1, таг2 потребителско име + Невалидна парола или ключов файл. + Невалиден алгоритъм. + Формат на базата данни не се разпознава. Файла на ключа не съществува. + Няма избран ключов файл. Файла с ключа е празен. Дължина Размер на груповия списък @@ -97,6 +143,8 @@ Настройка на базата данни Изтриване Премести в друга група + Премести + Отиди в родителската група Дарете бира... Редактиране Скрий парола @@ -128,13 +176,73 @@ Премахване Rijndael (AES) Главен + Шифрован кръг + По-високо криптиране на кръга осигурява допълнителна защита срещу атаки с груба сила, но може да забави зареждането и записването. + Име на базата данни + Потребителско име по подразбиране за нови записи + Записване на база данни... + Експортиране на база данни... + Базата данни е експортирана! + Пространство + Търсене + Покажи паролата + Сортирай по... + Сортиране по име + Сортирай по дата на създаване + Сортирай по дата на модификация + Запази ред по подразбиране + Специални + Търси + Резултати от търсенето + Търсене в + Изберете друг запис + Отворете желаната група, след което натиснете \"%1$s\"! + Вмъкни тук + Twofish + Подчертаване + Неподдържана версия на базата данни. + Главни букви + Sd картата е само за четене. Може да не успеете да запазите промените във вашата база данни. + Sd картата не е монтирана в момента на вашето устройство. Вие няма да можете да заредите или да създадете вашата база данни. + Версия + Хронология на версиите + Keepass2Android е разработена от Philipp Crocoll. + Благодарение на девелопера %1$s. + Благодарение на иконата и оформлението дизайн вноски от %1$s. + Twofish шифър плъгина за Keepass е разработен от Скот Грийнбърг и е включен в KP2A. + Android-filechooser е разработена от Хай бизони + KP2A клавиатурата се основава на Gingerbread клавиатурата от андроида отворен източник на проект и използва плъгин мениджър кода от клавиатурата на хакер от Клаус Weidner. + Моля, обърнете внимание + Сътрудници + Регулярен израз + Тан изтича на използване + Отбележи TAN записите с изтекъл срок при използването им + Показвано име в списъка + Показване на потребителските имена под заглавията. Полезно за няколко сметки или TAN-а + Запомни базите данни + Запомни последно отваряните бази данни ги показвай в екрана на отворената база данни. + Keepass2Android: Намери парола + Изключи изтеклите записи + Опции + Има разлика за голям-малък шрифт + Отваряне на файл... + Създаване на нова база данни... + Отваряне на URL... + Импортира файл в нова база данни + Пълен URL адрес трябва да се зададе, включително протокол като http://. + Файла за импортиране ще бъде избран в следващата стъпка. + Включете опцията \"Бързо отключване\" Въведете последните %1$d символа от вашата парола: Бързо отключване! Затвори базата данни Включи Бързо отключване по подразбиране Определя дали Бързо отключване е включено по подразбиране или не. + Защити показването на базата данни + Ако е включено, снимките на екрана са блокирани и превюто на програмата не се показва в текущите работещи приложения Скрий иконата за Бързо отключване Бързо отключване за съжаление не работи без да се показва нотификационна икона. Изберете тази опция за да използвате прозрачна икона. + Скрий иконата за Бързо отключване + QuickUnlock изисква уведомяване за да работи правилно. Изберете тази опция за показване на уведомление без икона. Дължина на ключа за Бързо отключване Максимален брой знаци използвани като парола за Бързо отключване. Бързо отключване НЕУСПЕШНО: невярна парола! @@ -146,6 +254,8 @@ Запази в кеша и отвори Файла е запазен в %1$s. Не може да запази приложения файл в %1$s. + Запомни текста за търсене? + Искате ли да съхраните търсения текст \"%1$s\" в избрания запис, за да го намерите автоматично следващия път? Невалиден формат за дата/време за изтекла дата! Име на полето е задължително за всеки стринг. Име на полето @@ -161,6 +271,13 @@ Използвай тракзакция на файлове за записване на бази данни Заключи когато изкл.екрана Заключи базата данни когато се изкл.екрана. + Изчиства въведената главна парола + Изчиства въведената главна парола ако напуснете екрана без отключване на базата данни + Заключване при излизане от приложението + Заключване на базата данни при излизане от приложението чрез натискане на бутона за връщане назад. + Скрий опцията за дарения + Тази настройка е за дарители. Тя е достъпна след използване на Keepass2Android за известно време. + Без дарения това приложение не може да съществува и няма да се подобрява непрекъснато! Ако сте все още не сте дарили, моля обмислете да го направите сега. Кеширане на базатаданни Запази копие на отдалечената база данни в кеф папката. Това позволява да се използва отдалечена база данни когато сте офлайн. SSL сертификати @@ -168,4 +285,60 @@ Изчисване на кеша? Това ще изтрие всички кефирани бази данни. Всички промени докато сте били офлайн които не са синхронизиране ще бъдат изгубени! Продължаване? Провери за промени + Проверява дали файлът е променен външно преди записване на промените. + Проверка за дублирани UUID + Проверете дали файлът на базата данни е повреден от наличието на множество записи със същия ИД. Това може да доведе до неочаквано поведение. + Уведомления от клипборда + Направи достъпни чрез лентата за уведомление и клипборда потребителското име и парола. Пазете се прехващачи на пароли! + Отделни уведомления + Показвай отделни съобщения за копиране на потребителско име и парола към clipboard и активиране от клавиатурата. + KP2A клавиатура уведомяване + Направете пълния запис достъпен чрез KP2A клавиатурата (препоръчва се). + Превключване на клавиатурата + Отвори диалог за избор на клавиатура когато стойност е налична през KP2A клавиатура след търсене от браузъра. + Автоматично превключване при рутнати устройства + Автоматично превключване към KP2A клавиатура, когато записът е отворен. Изисква рут достъп и Secure Settings приложение със System+. + Автоматично превключване само след търсене + Презаписване + Преименувай + Неуспешно добавяне на прикачен файл. + Кошче + Искате ли да изтриете този елемент окончателно? Натиснете не за рециклиране. + Искате ли да изтриете този елемент окончателно? Натиснете не за рециклиране. + Изтриване завинаги? + Презареди файла? + Файла който е отворен в момента е променен от друга програма. Искате ли да го презареди? + Базата данни е повредена: дубликат идентификатори намерени. (Знаете запишете с Minikeepass?) Моля да импортирате отново в нова база данни с Keepass 2 за PC и изберете \"Създай нов ИД\". + Можете да забраните това съобщение за грешка в приложението настройки/настройки/файл обработка/проверка за дублирани UUID. Моля, обърнете внимание, че е възможно да имате неочаквано поведение. Препоръчително е да се определи на базата данни. + Синхронизиране на базата данни... + Може да преместите група към тази група. + Днес тя е Октоберфест! Ако ви харесва Keepass2Android: днес няма да бъде един добър ден да ми купи една бира? + 10 май? Това е моят рожден ден! Ако ви харесва този ап, защо не ми изпратите някои рожден ден Поздрави заедно с малък подарък за рождения ден? Това наистина ще ме направи щастлив! :-) + О ти пропусна моя рожден ден на 10 май! Ако ви харесва този ап, защо не да ми изпратите някои рожден ден поздравления и малко подарък? Все още не е твърде късно, за да ме направи щастлив! :-) + Кажи ми повече! + Не, не ми харесва толкова много + host (ex: 192.168.0.1) + порт + Начална директория (по избор): + Въведете SFTP входните данни: + Изберете типа на съхранение: + Локален файл + Получи от трети партия app + Изпрати на трети партия app + FTP + HTTP (WebDav) + HTTPS (WebDav) + Dropbox + Dropbox (KP2A папка) + Ако не искате да дадете KP2A достъп до пълен живея, можете да изберете тази опция. Тя ще поиска достъп само до папката приложения/Keepass2Android. Това е особено подходящ, когато създавате нова база данни. Ако вече имате база данни, щракнете върху тази опция, за да създаде папката, след което поставете вашия файл в папката (от вашия компютър) и след това изберете тази опция отново за отваряне на файла. + Google Drive + OneDrive + SFTP (SSH прехвърляне на файлове) + Файла достъп инициализация + Database местоположение + Можете да съхранявате вашата база данни локално на вашето устройство Android или в облака (не офлайн версия само). Keepass2Android предоставя базата данни, дори ако сте офлайн. Тъй като базата данни е сигурно криптирани с AES 256 bit криптиране, никой няма да може да получите достъп до паролите ви освен вас. Препоръчваме да изберете Dropbox: тя е достъпна на всичките ви устройства и дори дава гръб на предишни версии на файлове. + Изберете къде искате да съхранявате в базата данни: + Промяна на местоположението + Главна парола + Вашата база данни е шифрована с парола, въведете тук. Изберете сигурна парола за да се запази базата данни безопасно! Съвет: Съставляват едно изречение или две и въведете първите букви на думите като парола. Включете препинателни знаци. diff --git a/src/keepass2android/Resources/values-ca/strings.xml b/src/keepass2android/Resources/values-ca/strings.xml index fca5cfd6..27be64b8 100644 --- a/src/keepass2android/Resources/values-ca/strings.xml +++ b/src/keepass2android/Resources/values-ca/strings.xml @@ -24,7 +24,7 @@ Temps abans de bloquejar la base de dades quan l\'applicació està inactiva. Matar el procés d\'aplicació Botó de tancament - Mostra, un botó a la pantalla de contrasenya per matar el procés d\'aplicació (per a usuaris paranoics) + Mostra un botó a la pantalla de contrasenya per matar el procés d\'aplicació (per a usuaris paranoics) Aplicació Paràmetres de l\'aplicació Mostra el nom de grup en el resultat de la cerca @@ -32,9 +32,9 @@ Grup mostrat ara: %1$s Mostra el nom de grup en vista d\'entrada Em sap greu! Keepass2Android no pot manejar les tornades URI %1$s. Si us plau, contacta amb el desenvolupador! - Securetat + Seguretat Mostrar - Accés amb d\'entrada de contrasenya + Accés amb entrada de contrasenya Desbloqueig ràpid Gestor d\'arxius Teclat @@ -65,6 +65,7 @@ Dígits Keepass2Android ve SENSE CAP MENA DE GARANTIA; Això és programari lliure, i pots redistribuïr-lo sota els termes de la llicència GPL versió 2 o posterior. \u2026 + Copiar al portapapers Introdueix el nom de la base de dades Accedida Cancel·la @@ -123,11 +124,14 @@ Algoritme invàlid. Format de base de dades desconegut. Arxiu clau no existeix. + Cap arxiu clau de seleccionat. + Arxiu clau és buit. Longitud Mida de la llista de grups Mida del text a la llista de grups Carregant base de dades… Minúscules + ***** Emmascara contrasenya Amaga les contrasenyes per defecte Sobre @@ -138,15 +142,23 @@ Paràmetres Paràmetres de la base de dades Esborra + Moure a un altre grup + Moure + Navegui al grup superior + Donar una cervesa... Editar Amaga contrasenya Bloqueja la base de dades Obre Reanomena Cerca + Cerca avançada Ves a la URL + Canvi de base de dades… Menys Mai + + No Sense entrades a la base de dades o grup. Cap resultat de cerca Sense gestor per aquesta url. @@ -155,42 +167,349 @@ Omet els grups \'Còpia de seguretat\' i paperera dels resultats de cerca Nom de base de dades KeePass Introdueix contrasenya de la base de dades + Seleccioneu el tipus de clau mestra: Creant nova base de dades… + Crear base de dades Treballant… Recorda la localització d\'arxius clau Guarda arxiu clau Elimina + Rijndael (AES) Arrel Passades d\'encriptació Més passades d\'encriptació dónen protecció adicional contra atacs de força bruta, però poden alentir molt carregar i guardar la base de dades. passades + Nom de la base de dades + Nom d\'usuari per defecte per noves entrades Guardant la base de dades… + Exportant la base de dades… + Base de dades exportada amb èxit! Espai Cerca Mostra contrasenya + Ordena per... Ordena per nom Ordenació de base de dades + Ordenar per data modificació + Mantenir l\'ordre per defecte Especial + Trobar el que Resultats de cerca + Cerca a + Selecciona una altra entrada + Obrir el grup desitjat i prémer \"%1$s\"! + Inserir aquí + Twofish Subratllat Versió de la base de dades no suportada. Majúscules La teva tarja SD és de només lectura. No podràs guardar canvis a la teva base de dades. La teva tarja SD no està muntada al teu dispositiu. No podràs carregar ni guardar una base de dades. Versió + Historial de versions + Keepass2Android és desenvolupat per Philipp Crocoll. + Gràcies a les aportacions de codi de %1$s. + Gràcies a les aportacions de disseny icona i disseny per %1$s. + El Plugin de xifratge Twofish per Keepass va ser desenvolupat per Scott Greenberg i està inclòs en KP2A. + androide-filechooser va ser desenvolupat per Hai bisó + El teclat de l\'KP2A es basa en el teclat de Gingerbread del projecte de font oberta Android i utilitza el codi del Gesto de Conectors del teclat Hacker per Klaus Weidner. + Tingueu en compte + Contribuïdors + Expressió regular + TAN expira en ús + Marca entrades TAN caducades quan siguin utilitzades + Mostra nom d\'usuari en llista + Mostrar noms d\'usuari sota títols d\'entrada. Útil per a comptes múltiples o TANs. + Recordeu les bases de dades + Recordeu les bases de dades recentment obertes i mostrar-les en la pantalla de d\'obrir base de dades. + Keepass2Android: Localitzar contrasenya + Excloure les entrades caducats + Opcions + Majúscules i minúscules + Obrir arxiu... + Crear base de dades nova... + Obrir URL... + Importar fitxer a nova base de dades... + Cal especificar l\'URL complet incloent protocol com http://. + En el següent pas serà seleccionat fitxer que voleu importar. + Permetre QuickUnlock + Introduir últims %1$d caràcters de la seva contrasenya: + QuickUnlock! + Tancar base de dades + Permetre QuickUnlock per defecte + Defineix si QuickUnlock està habilitada per defecte o no. + Protegir l\'exhibició de base de dades + Si està activat, no s\'admeten cap captura de pantalla i cap miniatura de l\'aplicació es mostra a la llista d\'aplicacions recents. + Amagar icona de QuickUnlock + Malauradament QuickUnlock no funciona sense mostrar una icona de notificació. Seleccioneu aquesta opció per utilitzar una icona transparent. + Amagar icona de QuickUnlock + QuickUnlock requereix una notificació per treballar pròpiament. Seleccioneu aquesta opció per mostrar una notificació sense una icona. + Longitud de clau QuickUnlock + Nombre màxim de caràcters utilitzats com a contrasenya de QuickUnlock. + QuickUnlock ha fallat: Contrasenya incorrecta! + Directori d\'arxius adjunts + Directori on es guarden els fitxers adjunts. + Deseu el fitxer adjunt + Si us plau seleccioneu on voleu desar el fitxer adjunt. + Desar a la targeta SD + Desa a la memòria cau i obre + Desat l\'arxiu a %1$s. + No s\'ha pogut desar el fitxer adjunt a %1$s. + Recordeu el text de cerca? + Voleu emmagatzemar text de la cerca \"%1$s\" a l\'entrada seleccionada per tal de trobar-lo automàticament la propera vegada? + Format de data/hora no vàlid per a la data de caducitat! + Cal un nom de camp per a cada cadena. + Nom del camp + Valor del camp + Camp protegit + Afegir el fitxer adjunt... + Afegir la cadena addicional + Suprimir la corda addicional + %1$s: bloquejat. QuickUnlock activat. + %1$s: desbloquejat. + Introduïu les credencials del servidor + Operacions d\'arxiu + Utilitzar les operacions d\'arxiu per escriure les bases de dades + Bloqueja quan la pantalla s\'apagui + Bloqueja la base de dades quan la pantalla s\'apagi. + Esborra la contrasenya mestra introduïda + Esborra la contrasenya mestra introduïda en deixar la pantalla sense obrir la base de dades. + Bloqueja quan surtis de l\'aplicació + Tancar la base de dades en deixar l\'aplicació prement el botó endarrere. + Amagar l\'opció de donació + Aquesta configuració és pels donants. Està disponible després d\'utilitzar Keepass2Android durant un temps només. + Sense les donacions, aquest aplicació no existiria i no milloraria contínuament! Si vostè encara no ha donat, si us plau consideri fer una donació ara. + Posant en memòria cau la base de dades + Manté una còpia de la base de dades remota en el directori de memòria cau de l\'aplicació. Això permet utilitzar bases de dades remotes fins i tot quan esteu fora de línia. + Certificats SSL + Defineix el comportament quan fracassa validació de certificat. Nota: podeu instal·lar certificats en el dispositiu si fracassa la validació! + Neteja la memòria cau? + Se suprimiran tots els arxius de base de dades en memòria cau. Els canvis que heu realitzat mentre sou fora de línia i que encara no han estat sincronitzat es perdran! Voleu continuar? + Comprovar per modificacions + Comprovar si l\'arxiu va ser modificat externament abans de desar els canvis. + Comprovar per duplicats de UUIDs + Comprova si l\'arxiu de base de dades és corrupte mirant si te diverses entrades amb el mateix identificador. Això podria provocar comportaments inesperats. + Notificacions de porta-retalls + Fer l\'usuari i contrasenya accessible a través de la barra de notificació i porta-retalls. Compte amb sniffers de contrasenya! + Notificacions independents + Mostrar les notificacions separades per copiar el nom d\'usuari i contrasenya al porta-retalls i activant el teclat. + Notificació de teclat KP2A + Fes entrada totalment accessible a través del teclat KP2A (recomanat). + Canvi de teclat + Diàleg de selecció de teclat obert quan l\'entrada està disponible a través de teclat KP2A després de cerca del navegador. + Canvi automàtic en dispositius amb accés de superusuari (root) + Canvia automàticament a KP2A teclat quan s\'obre la entrada. Requereix accés superusuari (root) i l\'aplicació Secure Settings amb System+. + Canvi automàtic només després de cerca + Només canvia automàticament a KP2A teclat després d\'utilitzar la funció de compartir URL (però no en obrir una entrada d\'una altra manera) + Torna a canviar el teclat + Canviar altra vegada a teclat previ quan no s\'obre cap entrada. + Icona de notificació mentre estigui desbloquejat + Mostra una icona de notificació mentre la base de dades està desbloquejada. + Pre-carregar el fitxer de base de dades + Comença carregant de fons o descàrrega de l\'arxiu de base de dades durant l\'entrada de contrasenya d\'inici. + Voleu sobreescriure el binari existent amb el mateix nom? + Voleu sobreescriure binari existent? + Sobreescriure + Canvia el nom + No s\'ha pogut afegir el fitxer adjunt. + Paperera de reciclatge + Voleu suprimir permanentment aquesta entrada? Prem No per reciclar. + Voleu suprimir permanentment aquesta entrada? Prem No per reciclar. + Suprimeix permanentment? + Recarregar fitxer? + L\'arxiu que és actualment obert es va canviar per un altre programa. Voleu actualitzar-lo? + Voleu descartar els canvis fets realment? (El botó de salvar és a la part superior del formulari.) + Descarta els canvis? + Suggerir o votar per millores + Valora aquesta app + Traduir KP2A + Afegir entrada… + Afegir grup… + Suprimint l\'entrada… + Suprimint grup… + Fixar contrasenya… + Desfer els canvis… + Transformant la clau mestra… + Descodificant la base de dades… + Anàlisi de base de dades… + Comprovació fitxer de destinació per canvis… + Combina els canvis? + L\'arxiu de base de dades es va modificar externament. Voleu carregar i fusionar els canvis abans de desar? Seleccioneu No si voleu sobreescriure els canvis externs. + Fusionant canvis… + Sí, fusionar + No, sobreescriure + Sincronitzar la base de dades en memòria cau… + Descarregar fitxer remot… + Carregant arxiu… + Restaurant fitxer remot… + Els arxius estan sincronitzats. + Base de dades se sincronitzada amb èxit! + Comprovació de la base de dades per canvis… + No s\'ha pogut desar a remot: %1$s. Torneu a desar o utilitzeu el menú sincronitza quan la connexió remota estigui disponible una altra vegada. + No es pot obrir remot: %1$s. Carregat el fitxer de memòria cau local. Encara podeu fer canvis a la base de dades i sincronitzar-los més tard. + Actualitzat fitxer remot. + Obert arxiu local degut al conflicte amb els canvis en el fitxer remot. Fes servir menú de Sincronitzar per fusionar. + Fitxer remot i memòria cau estan sincronitzats. + Actualitzat la còpia de la memòria cau local de %1$s. + No s\'han detectat canvis. + Actualitzada memòria cau del fitxer auxiliar OTP: Comptador remot era més alt. + Actualitzada memòria cau del fitxer auxiliar OTP: Comptador local era més alt. + S\'estan sincronitzant els fitxers auxiliars OTP… + l\'arxiu de base de dades + Arxiu auxiliar OTP + S’ha produït un error: + Base de dades és corrupte: identificadors duplicats trobats. (Vols guardar-ho amb Minikeepass?) Si us plau, torneu a importar a una nova base de dades amb Keepass 2 per a PC i seleccioneu \"Crea un nou ID\". + Podeu desactivar aquest missatge d\'error en Configuració/Configuració d\'aplicacions/Gestor d\'arxius/Comprova UUIDS duplicats. Tingueu en compte que vostè pot experimentar comportaments inesperats. Es recomana arreglar la base de dades. + Sincronitzar la base de dades… + No es pot desplaçar el grup a aquest grup. + Avui és Oktoberfest! Si t\'agrada Keepass2Android: no seria avui un bon dia per comprar-me una cervesa? + 10 de maig? És el meu aniversari! Si t\'agrada aquest aplicació, per què no enviar-me algunes salutacions d\'aniversari amb un petit regal d\'aniversari? Això realment em faria feliç! :-) + Ah, et vas perdre el meu aniversari el 10 de maig! Si t\'agrada aquest aplicació, per què no enviar-me algunes salutacions d\'aniversari i un regal d\'aniversari poc? Encara no és massa tard per fer-me feliç! :-) + Explica\'m més! + No, no m\'agrada tant + amfitrió (ex: 192.168.0.1) + port + Directori inicial (opcional): + Introduir dades de connexió SFTP: + Seleccioneu el tipus d\'emmagatzematge: + Fitxer local + Obtenir de l\'aplicació de tercers + Enviar a l\'aplicació de tercers + FTP + HTTP (WebDav) + HTTP (WebDav) + Dropbox + Dropbox (carpeta de KP2A) + Si no voleu donar accés KP2A al seu Dropbox complet, podeu seleccionar aquesta opció. Es sol·licitarà només l\'accés a la carpeta Apps/Keepass2Android. Això és especialment adequat quan es crea una nova base de dades. Si ja teniu una base de dades, feu clic a aquesta opció per crear la carpeta, a continuació, posar el seu arxiu dins la carpeta (des del seu PC) i llavors seleccioni aquesta opció nou per obrir l\'arxiu. + Google Drive + OneDrive + SFTP (SSH Transferència de fitxer) + Inicialització d\'accés a arxiu + Localització de la base de dades + Pot emmagatzemar la base de dades local o al seu dispositu Android o en el núvol (només versió fora de línia). Keepass2Android fa la base de dades disponible fins i tot si vostè està fora de línia. La base de dades segura, encriptada amb AES de 256 bits, ningú no podrà accedir a les vostres contrasenyes excepte vostè. Es recomana seleccionar Dropbox: és accessible a tots els seus mecanismes i fins i tot proporciona còpies de seguretat de versions anteriors d\'arxiu. + Seleccioneu on voleu emmagatzemar la base de dades: + Canvia la ubicació + Contrasenya mestra + La base de dades s\'encripta amb la contrasenya que introduïu aquí. Triar una contrasenya forta per tal de mantenir la base de dades segura! Consell: Forma una frase o dues i utilitzar les primeres lletres de les paraules com a contrasenya. Inclou signes de puntuació. + Seleccioni una contrasenya mestra per protegir la seva base de dades: + Arxiu clau + Un arxiu clau és bàsicament una contrasenya s\'emmagatzema en un arxiu. Els arxius clau són normalment més forts que les contrasenyes mestres, perquè la clau pot ser molt més complicada; però també és més difícil mantenir el secret. Si emmagatzema la base de dades en el núvol, no emmagatzemi l\'arxiu clau també! Això ho faria completament inútil! Important: No canvieu el contingut del fitxer clau després de crear la base de dades! + Trieu si voleu utilitzar un arxiu clau a més de la contrasenya mestra: + Fes servir la clau + Error en afegir l\'arxiu clau! + Càrrega arxiu OTP auxiliar… + Introduïu la següent Contrasenya-d\'un-sol-us (One-time-passwords OTPs). Llisca la teva Yubikey NEO al darrere el seu dispositiu per entrar mitjançant NFC. + OTP %1$d + No puc trobar un aplicació que pugui manegar el desafiament. Si us plau instal·la Yubichallenge del Google Play. + No s\'ha pogut carregar el fitxer OTP auxiliar! + Si us plau, utilitzeu el connector OtpKeyProv de KeePass 2. x (PC) per configurar la base de dades per usar amb OTPs! + Seleccioneu primer de base de dades. OTP es descarta per motius de seguretat. + OTP descartat: tots els OTPs ja entrats! + Si us plau, tanqueu primer la base de dades. Es descarta OTP. + (Un o més OTPs ja disponibles) + OTP secret (p. ex. 01 23 ab cd...) + Error passant OTP secret! + No ha pogut crear la clau OTP! Assegureu-vos que ha introduït els OTPs correctes. + Error actualitzant fitxer OTP auxiliar! + Salvant arxiu OTP auxiliar… + La resposta de desafiament és incorrecte. + No s\'ha pogut carregar el fitxer de repte auxiliar! + Utilitzeu el connector KeeChallenge de KeePass 2. x (PC) per configurar la base de dades per al seu ús amb repte-resposta! + Error actualitzant fitxer OTP auxiliar! + Nom del camp TOTP llavor + Si està utilitzant el connector de Keepass 2 \"TrayTotp\" amb la configuració de modificada introduïu el nom de camp per al camp llavor aquí segons la configuració en el PC. + Ajustaments del nom del camp TOTP + Introduïu aquí el nom del camp dels ajustaments del camp TrayTotp. + TrayTotp + Carregant… + Connectors + Nom del paquet: + Descripció (no verificat): + L\'autor (no verificat): + activat + desactivat + Trobar connectors en línia + Permisos de nivell + %1$s sol·licita credencials per %2$s. + %1$s sol·licita credencials. Si us plau seleccioni una entrada. + Activat + Notificacions d\'acció de base de dades + El connector avisaran quan una base de dades és oberta, tancada o salvada. + Dades d\'entrada actual + El connector rebrà totes les dades sobre l\'entrada de base de dades actual i se li permetrà oferir accions i modificacions de com es mosta aquesta. + Consulta credencials pròpies + El connector permetrà consultar les credencials associades amb el seu propi paquet d\'aplicació. + Consulta les credencials + El connector permetrà a les credencials consultes per a aplicacions o llocs web. + Aconseguir més tipus d\'emmagatzematge + Advertència: Ha fallat la validació de certificat de servidor: %1$s. Instal·lar el certificat arrel adequat al vostre dispositiu o consulti els ajustaments! + Error: Validació de certificat de servidor fracassat! Instal·li el certificat arrel adequat al vostre dispositiu o veure configuració! + Seleccioneu el format de fitxer + Em sap greu! Keepass2Android fou matat pel Sistema Operatiu d\'Android! Per motius de seguretat, Keepass2Android no persisteixen les vostres credencials seleccionade al disc, pel que cal tornar a obrir la base de dades. Nota: Això succeeix molt poques vegades. Si ho fa, si us plau envieu-me un missatge a crocoapps@gmail.com. + L\'arxiu només està disponible temporalment per Keepass2Android. + El fitxer que heu seleccionat és només de lectura. + El fitxer que heu seleccionat és només de lectura per a Keepass2Android a causa de restriccions en Android 4.4 +. + Per utilitzar-lo, haureu de copiar-lo a una altra ubicació. + Per editar-lo, haureu de copiar el fitxer a una altra ubicació. + Clic Acceptar per seleccionar una ubicació on cal copiar l\'arxiu. + Cancel·lar, obrir només de lectura. + Copiant el fitxer... + Tingueu en compte: que heu carregat una base de dades de Keepass 1. Keepass2Android ha afegit recentment suport d\'escriptura per a aquest format de base de dades. A pesar de les proves, l\'autor no garanteix que totes les dades es guardin correctament. Si us plau sempre mantingueu una còpia de seguretat de la base de dades original (Dropbox automàticament emmagatzema versions recents) abans de fer canvis. Si us plau informeu de qualsevol incidència. Gràcies! + Registre de canvi + Atenció! Això és un versió prèvia i pot arribar amb alguns defectes! Si vostè experimenta *qualsevol* comportament inesperat, si us plau, faci-m\'ho saber (a Codeplex o per correu electrònic). + Versió 0.9.7\n + * suport per escriure a bases de dades Keepass 1 (kdb) (beta!) \n + * millor canviar a teclat anterior (també treballa en dispositius que no disposin d\'accés de superusuari - rootejats)\n + * suport per a KeeChallenge amb challenges\n de longitud variable\n + * evitar prendre captures de pantalla des de les pantalles de QuickUnlock i contrasenya\n + * ordenació inversa per Ordena per data de modificació (ara descendent) \n + * errors arreglats: vista de notes ara actualitzada correctament després de canvis, vistes de contrasenyes ara amaga contrasenya correctament en (esperançadorament) tots els dispositius, arreglat problema que li permetia afegir una entrada doble , solucionat el problema que mostrava avís de duplicat UUID fins i tot després d\'arreglar la base de dades\n + + Version 0.9.6\n * allow to import key file and/or local database file to app internal directory (see settings)\n * allow different sorting options\n * improved preferences for automatic keyboard switching\n * updated application logo and notification design, design by Stefano Pignataro (http://www.spstudio.at)\n * password generator remembers last settings\n * set notification visibility for Android 5 lock screen\n * now clearing master password field when leaving the app without clicking OK\n * fixed issue with missing input languages in keyboard setting on some devices\n * fixed issue with automatic keyboard switching on rooted devices\n * added check for corrupt databases (duplicate UUIDs)\n * automatically reload database when change detected, solves security concern about revealing master password\n * improved polish small keyboard layout, fixed keyboard settings theme (thanks to Wiktor Ławski)\n + +Versió 0.9.5 \n * Arreglat problemes amb arxiu de navegació (especialment en Android 4.4) \n * Solucionat el problema amb la càrrega d\'arxius .kdb (Keepass 1) amb el Nexus 5 amb Android Lollipop\n * afegit l\'opció per evitar prendre screenshots/mostrant app a la llista d\'aplicacions recents\n * Solucionat el problema amb Google Drive arxiu d\'emmagatzematge (edició regular) \n * Permeten arxius clau en emmagatzematge deliberada tipus (edició regular) \n * SDK de Dropbox actualitzat per incloure un pedaç de seguretat oficial (edició regular) \n * Actualitzades eines de construcció--> mida dels apk augmentada:-(\ n He promès alguns canvis més. Vindran amb el pròxim llançament- Ho sentim. Volia publicar aquests destrets calents tan aviat com sigui possible. + Estesa possibilitat de donar una cervesa o una altra cosa 30 segons 1 minut 5 minuts - 10 minutes - 15 minutes - 30 minutes - 1 hour - Never + 10 minuts + 15 minuts + 30 minuts + 1hora + Mai + + + Base de dades KeePass 2 (.kdbx) + KeePass 2 XML (sense xifrar) (. xml) + KeePass CSV (sense xifrar) (. csv) Petita Mitjana Gran + + Holo Clar + Holo Fosc + + Disseny + + No recordo l\'usuari i contrasenya + Recordar només nom d\'usuari + Recordar nom d\'usuari i contrasenya + + + Contrasenya només + Contrasenya + arxiu de clau + Contrasenya + OTP + Contrasenya + OTP secret (mode de recuperació) + Contrasenya + repte-resposta + Contrasenya + resposta repte secret (mode de recuperació) + + + Ignora els errors de validació de certificat + Avisa quan fracassi validació + No admetre els certificats no vàlids + diff --git a/src/keepass2android/Resources/values-cs/strings.xml b/src/keepass2android/Resources/values-cs/strings.xml index bb44d12b..69b49856 100644 --- a/src/keepass2android/Resources/values-cs/strings.xml +++ b/src/keepass2android/Resources/values-cs/strings.xml @@ -65,6 +65,7 @@ Číslice Keepass2Android je dodáván BEZ JAKÉKOLIV ZÁRUKY; Toto je svobodný software, můžete jej šířit pod licencí GPL verze 2 nebo novější. \u2026 + Kopírovat do schránky Zadejte název souboru databáze Poslední přístup Storno diff --git a/src/keepass2android/Resources/values-da/strings.xml b/src/keepass2android/Resources/values-da/strings.xml index 5586370f..7392580e 100644 --- a/src/keepass2android/Resources/values-da/strings.xml +++ b/src/keepass2android/Resources/values-da/strings.xml @@ -65,6 +65,7 @@ Cifre Keepass2Android leveres ABSOLUT UDEN GARANTI. Det er gratis software, og du er velkommen til at videredistribuere det under betingelserne i GPL version 2 eller senere. \u2026 + Kopiér til upklipsholder Angiv navn på databasefil Seneste åbnede Annuller @@ -172,6 +173,7 @@ Gem nøglefil Fjern Rijndael (AES) + Rod Krypterings-gentagelser Højere krypterings-gentagelser giver øget beskyttelse imod brute-force angreb, men kan påvirke læsnings- og skrivehastigheden betydentligt. gentagelser @@ -183,8 +185,11 @@ Mellemrum Søg Vis adgangskode + Sorter efter... Sorter efter navn DB sorteringsrækkefølge + Sorter efter ændringsdato + Behold standardrækkefølgen Speciel Find hvad Søgeresultater @@ -200,7 +205,9 @@ Dit sd-kort er ikke monteret i din enhed. Du vil ikke være i stand til at indlæse eller oprette din database. Version Versionshistorik + Keepass2Android er udviklet af Philipp Crocoll. Tak for kodebidrag af %1$s. + Tak til ikon- og layoutdesignbidrag af %1$s. Twofish Cipher-plugin\'et til KeePass blev udviklet af Scott Greenberg og er inkluderet i KP2A. android-file-chooser blev udviklet af Hai Bison KP2A-tastaturet er baseret på Gingerbread-tastaturet fra Android Open Source Project og bruger Plugin Manager-koden fra Hacker\'s Keyboard af Klaus Weidner. @@ -229,6 +236,7 @@ Luk database Aktiver Hurtigoplåsning som standard Definerer, om Hurtigoplåsning er aktiveret som standard eller ej. + Beskyt databasevisning Skjul Hurtigoplåsning-ikon Hurtigoplåsning virker desværre ikke uden at vise et beskedikon. Vælg denne indstilling for at bruge et gennemsigtigt ikon. Skjul Hurtigoplåsning-ikon @@ -236,6 +244,13 @@ Længde af nøgle til Hurtigoplåsning Maksimalt antal tegn brugt som nøgle til Hurtigoplåsning. Hurtigoplåsning mislykkedes: Forkert nøgle! + Gem vedhæftet fil + Vælg hvor du vil gemme den vedhæftede fil. + Gem på SD-kort + Gem til cache og åben + Gemt fil som %1$s. + Kunne ikke gemme den vedhæftet fil %1$s. + Husk søgetekst? %1$s: Låst. Hurtigoplåsning aktiveret. 30 sekunder diff --git a/src/keepass2android/Resources/values-de/strings.xml b/src/keepass2android/Resources/values-de/strings.xml index a1d170f7..9511f075 100644 --- a/src/keepass2android/Resources/values-de/strings.xml +++ b/src/keepass2android/Resources/values-de/strings.xml @@ -385,6 +385,7 @@ Der Android Robot wird genutzt und wurde modifiziert basierend auf Arbeiten, die Google Drive OneDrive SFTP (SSH File Transfer) + Android-Dateibrowser Dateizugriff initialisieren Speicherort der Datenbank Du kannst deine Datenbank lokal auf deinem Android-Gerät oder in der Cloud speichern (nur in der Nicht-Offline-Version). Keepass2Android macht die Datenbank dann auch verfügbar, wenn du offline bist. Da die Datenbank sicher mit der AES 256-Bit-Verschlüsselung geschützt ist, erhält auch dann niemand außer dir Zugriff auf deine Datenbank. Wir empfehlen die Benutzung von Dropbox: Es ist auf allen Geräten verfügbar und bietet automatisch Backups aller Dateiversionen. @@ -458,6 +459,25 @@ Der Android Robot wird genutzt und wurde modifiziert basierend auf Arbeiten, die Bitte beachten: Du hast eine Keepass-1-Datenbank geladen. Keepass2Android bietet seit kurzem die Möglichkeit, solche Dateien zu editieren. Trotz gründlicher Tests garantiert der Autor nicht, dass alle Daten korrekt gespeichert werden. Bitte lege immer eine Sicherheitskopie der ursprünglichen Datenbank an, bevor du mit Keepass2Android speicherst (Tipp: Dropbox speichert automatisch ältere Verionen). Sollte ein Problem auftreten, melde diese bitte an den Autor. Danke! Neuigkeiten Bitte beachten! Dies ist eine Vorab-Version, die einige Fehler enthalten könnte! Wenn du *irgendetwas* unerwartetes feststellen solltest, lass es mich bitte wissen (auf Codeplex oder per E-Mail). + Fortfahren + Der eingegebene Pfad scheint kein gültiger Dateiname zu sein. Bist du sicher, dass es sich um eine gültige Datei handelt? + The URI you have entered does not look like a filename. Are you sure this is a valid file? + + Version 0.9.8b\n + * Bugs behoben: Speichern schlug bei manchen Datenbanken fehl, Exportieren mit lokalem Ziel funktionierte nicht, manche Einstellungsoptionen führten zum Absturz\n + + Version 0.9.8\n + * Unterstützung für das Storage Access Framework (ermöglicht Schreiben auf SD-Karte und auf Google Drive mit KP2A Offline)\n + * Fehlerhafte Benutzereingaben bei WebDAV-URLs werden wenn möglich erkannt (Verzeichnis statt Datei)\n + * Passwort-Schriftart geändert\n + * Dropbox-Konto kann gewechselt werden\n + * Bug-Fix: Passwort-Art bei OTP wird gespeichert\n + * Hinweis: Ich hatte Material-Design für dieses Release versprochen. Es ist in Arbeit, braucht aber noch ein bisschen mehr Zeit. Sorry! + + Version 0.9.7b\n + * Übersetzungen aktualisiert\n + * Bugs behoben: Passwort-Schriftart fehlte in 0.9.7, Gruppen wurden nicht sortiert, wenn \"Sortieren nach Namen\" ausgewählt war\n + Version 0.9.7\n * Schreibunterstützung für Keepass 1 (kdb) Datenbanken (Beta!)\n diff --git a/src/keepass2android/Resources/values-es/strings.xml b/src/keepass2android/Resources/values-es/strings.xml index 23c2c152..fa0a9255 100644 --- a/src/keepass2android/Resources/values-es/strings.xml +++ b/src/keepass2android/Resources/values-es/strings.xml @@ -65,6 +65,7 @@ Dígitos Keepass2Android NO TIENE TOTAL GARANTÍA; Este es software libre, y puedes redristribuirlo bajo las condiciones de la licencia GPL version 2 o posterior. \u2026 + Copiar al portapapeles Introduzca el nombre del archivo de base de datos Accedido Cancelar diff --git a/src/keepass2android/Resources/values-fi/strings.xml b/src/keepass2android/Resources/values-fi/strings.xml index 5e528605..bf893d6d 100644 --- a/src/keepass2android/Resources/values-fi/strings.xml +++ b/src/keepass2android/Resources/values-fi/strings.xml @@ -2,15 +2,15 @@ - Anna palautetta + Palaute Kotisivu Keepass2Android on salasanojen hallintaohjelma, jolla voit lukea ja kirjoittaa KeePass 2.x versioiden tietokantoja Androidilla. - Käyttöliittymä perustuu Brian Pellinin kehittämään KeepassDroid -porttaukseen. Tietokantatoimintojen lähdekoodi perustuu Dominik Reichlin KeepPass -sovellukseen. Android robotti on jäljennetty tai muokattu Googlen jakamista teoksista ja sitä käytetään Creative Commons 3.0 Attribution Licensensen kuvaamien ehtojen mukaisesti. - SFTP tuki toteutuu JSch Kirjaston BSD lisenssillä luomaa JCraft, Inc:a käyttämällä. + Käyttöliittymä perustuu Brian Pellinin kehittämään KeepassDroid -porttaukseen. Tietokantatoimintojen lähdekoodi perustuu Dominik Reichlin KeePass -sovellukseen. Android Robot on kopioitu tai muokattu Googlen jakamista julkaisuista ja sitä käytetään Creative Commons 3.0 Attribution Licensen kuvaamien ehtojen mukaisesti. + SFTP tuki toteutetaan käyttämällä JSch Kirjastoa BSD lisenssillä, jonka on luonut JCraft, Inc. Hyväksy - Estä + Älä hyväksy Lisää merkintä - Luo merkintä URLi:sta + Luo tapahtuman URL Lisää ryhmä Lisää ryhmä Muokkaa ryhmää @@ -18,7 +18,7 @@ Algoritmi Keepass2Android KP2A - Keepass2Android Offline + Keepass2Android offline-tila KP2A Offline Aikakatkaisu Aika jonka jälkeen tietokanta lukkiutuu automaattisesti jos ohjelmaa ei käytetä. @@ -27,11 +27,11 @@ Näytä painike \"Tapa prosessi\" (vainoharhaisille käyttäjille) Sovellutus Asetukset - Näytä ryhmänimen hakutulos + Ryhmänimet hakutuloksissa Näyttää ryhmänimien alla merkintöjen otsikot hakutuloksissa. Hyödyllinen, jos on useita saman nimisiä. Nyt näytettävä ryhmä on: %1$s - Näytä ryhmän nimi merkinnässä - Anteeksi! Keepass2Android ei voi käsitellä palautettua URI-%1$s. Ota yhteyttä kehittäjään! + Ryhmien nimet merkinnöissä + Keepass2Android ei voi käsitellä palautettua URI-%1$s. Ota yhteyttä kehittäjään! Turvallisuus Näyttö Salasanavalinnat @@ -39,7 +39,7 @@ Tiedostokäsittely Näppäimistö Vie tietokanta... - Tuo tietokanta sisäisen kansioon + Tuo tietokanta sisäiseen kansioon Tuo avaintiedosto sisäiseen kansioon Näppäimistön vaihtaminen Saatavilla vain paikallisia tiedostoja. @@ -51,13 +51,13 @@ Peruuta Leikepöytä tyhjennetty. Leikepöydän aikakatkaisu - Aika ennen kuin leikepöytä tyhjennetään tunnuksista - Valitse kopioidaksesi käyttäjänimen leikepöydälle + Aika ennen kuin leikepöytä tyhjennetään + Valitse ja kopioi käyttäjänimi leikepöydälle Valitse ja kopioi salasana leikepöydälle Merkintä saatavana KP2A näppäimistölle on saatavilla Näppäimistön valinta-ikkunaa ei voitu avata. Aktivoi näppäimistö manuaalisesti. - Ota käyttöön Keepass2Android-näppäimistö Järjestelmäasetuksissa. + Ota käyttöön Keepass2Android-näppäimistö Sovellutus-asetuksissa. Luodaan tietokanta-avain... Nykyinen ryhmä Nykyinen ryhmä: Root @@ -65,6 +65,7 @@ Numerot Keepass2Androidissa ei ole mukana takuuta; Tämä on vapaa ohjelmisto ja sitä saa levittää GPL-version 2 tai uudemman mukaan. \u2026 + Kopioi leikepöydälle Kirjoita tietokannan tiedostonimi Käytetty Peruuta @@ -98,7 +99,7 @@ Nimi on pakollinen. Salasana tai avain pääavain on pakollinen. Täytyy valita ainakin yksi salasanan generointityyppi - Salasanat eivät täsmää. + Salasanat ei täsmää. Kierrokset täytyy olla numeroina. Otsikko on pakollinen. Kirjoita pituus-kenttään positiivinen kokonaisluku @@ -160,11 +161,11 @@ Ei Ei merkintöjä tietokannassa tai ryhmissä. Ei hakutuloksia - Ei URL-käsittelijää tälle osoitteelle. + Ei URL-käsittelyä tälle osoitteelle. Avaa edellinen tietokanta (Klikkaa) Älä etsi varmuuskopioista ja roskakorista Jätä \"Varmuuskopio\" ja roskakori pois hakutuloksista - KeePass-tietokannan tiedostonimi + KeePass-tietokannan nimi Syötä tietokannan salasana Valitse pääavaimen tyyppi: Luodaan uutta tietokantaa... @@ -186,10 +187,10 @@ Välilyönti Haku Näytä salasana - Lajittele... + Järjestä... Järjestä nimen mukaan Järjestä luontipäivän mukaan - Lajittele muokkauspäivämäärän mukaan + Järjestä muokkauspäivämäärän mukaan Pidä oletusjärjestys Erikoismerkit Kirjoita haku @@ -208,14 +209,15 @@ Versiohistoria Keepass2Androidin on kehittänyt Philipp Crocoll. Kiitä avustamalla koodilla %1$s. + Kiitos! Kuvakkeet ja sijoittelun suunnitteli %1$s. Keepass Twofish Cipher -lisäosan on kehittänyt Scott Greenberg ja se sisältyy KP2A:han. Android-tiedostonvalitsimen on kehittänyt Hai Bison - KP2A Android -näppäimistö perustuu Gingerbread-näppäimistöön ja Android Open Source Projectin avoimeen lähdekoodiin ja käyttää Klaus Weidnerin kehittämästä Hacker\'s Keyboardista liitännäisten hallinnointikoodia. + KP2A Android -näppäimistö perustuu Gingerbread-näppäimistöön ja Android Open Source Projectin avoimeen lähdekoodiin. Se käyttää Klaus Weidnerin kehittämästä Hacker\'s Keyboardista liitännäisten hallinnointikoodia. Huomaa Kehittäjät ja avustajat Säännöllinen lauseke TAN käytön päättyminen - Ilmoita vanhentuneiden TAN-merkintöjen käytöstä + Ilmoita vanhentuneiden TAN-merkintöjen käyttö Näytä käyttäjätunnus Näytä käyttäjätunnukset otsikon alla merkinnöissä. Hyödyllinen tietueen arvoissa tai TAN-Merkinnöissä. Muista tietokannat @@ -285,7 +287,7 @@ Tämä poistaa kaikki välimuistiin tallennetut tietokantatiedostot. Yhä synkronoimattomat offline-tilassa tehdyt muutokset menetetään! Haluatko jatkaa? Tarkista muutokset Tarkista, onko tiedostoa muokattu ulkoisesti ennen sen tallentamista. - Tarkista UUID-kaksoiskappaleiden varalta + Tarkista UUID dublikaattien varalta Tarkista onko tietokantatiedosto korruptoitunut niin, että siinä on monta merkintää samalla tunnusnumerolla. Se saattaa aiheuttaa ohjelman odottamatonta toimintaa. Leikepöydän ilmoitukset Käyttää käyttäjätunnusta ja salasanaa Ilmoituspalkin ja Leikepöydän kautta. Varo salasanan paljastumista! @@ -299,13 +301,13 @@ Vaihtaa automaattisesti KP2A-näppäimistöön, kun merkintä on avattu. Vaatii pääkäyttäjätilin ja Secure Settings -ohjelman System+:lla. Automaattivaihto vain haun jälkeen - Vaihtaa automaattisesti KP2A-näppäimistöön, kun käytetään Jaa URL -toimintoa (mutta ei avatessa merkintää muilla tavoin) + Vaihtaa automaattisesti KP2A-näppäimistöön, kun käytetään URL -toimintoa (mutta ei avatessa merkintää muilla tavoin) Näppäimistön vaihto takaisin Vaihda takaisin edelliseen näppäimistöön, kun merkintää ei ole avattu. - Ilmoituskuvake kun on lukitsematon + kun ilmoituskuvake on lukitsematon Näytä ilmoituskuvake kun tietokanta on avattu. Esilataa tietokanta - Aloita tietokantatiedoston taustalataus salasanan syöttövaiheessa. + Aloita tietokannan lataus taustalla salasanan syöttövaiheessa. Haluatko korvata nykyisen binääritiedoston samalla nimellä? Haluatko korvata nykyisen binääritiedoston? Korvaa @@ -358,11 +360,12 @@ OTP-lisätiedosto Tapahtui virhe: Tietokanta on korruptoitunut: siitä löytyi kahdentuneita tunnistenumeroita. (Tallensitko Minikeepass:lla?) Ole hyvä ja tuo tiedot uuteen tietokantaan KeePass 2:n PC-versiolla ja valitse \'Luo uudet ID-numerot\'. - Voit poistaa tämän virheilmoitukset valitsemalla Asetukset/Sovellutus/Tiedostokäsittely ja Tarkista kaksoiskappaleiden UUID. Huomioi että tämä voi aiheuttaa ongelmia. On suositeltavaa korjata tietokanta. + Voit poistaa tämän virheilmoitukset valitsemalla Asetukset/Sovellutus/Tiedostokäsittely ja Tarkista dublikaattien UUID. Huomioi että tämä voi aiheuttaa ongelmia. On suositeltavaa korjata tietokanta. Synkronoi tietokanta... Ryhmää ei voi siirtää tähän ryhmään. Tänään on Oktoberfest! Jos pidät Keepass2Androidista: Tänään olisi hyvä päivä ostaa minulle olutta? 10. maaliskuuta? Se on syntymäpäiväni! Jos pidät tästä ohjelmasta, miksipä et lähettäisi minulle syntymäpäiväonnitteluja pienen lahjan kera? Se tekisi minut todella onnelliseksi! :-) + Voih! Unohdit syntymäpäiväni 10. Toukokuuta ! Jos pidät tästä sovellutuksesta niin etkö voisi lähettää minulle syntymäpäiväterveisiä ja pientä syntymäpäivälahjaa? Vielä ehdit tehdä minut onnelliseksi! :-) Kerro lisää! Ei, en pidä sitä niin paljon isäntä (ex: 192.168.0.1) @@ -402,21 +405,21 @@ OTP-lisätiedostoa ei voi ladata! Käytä OtpKeyProv-liitännäistä KeePass 2.x:ssa (PC) ja määritä tietokanta käytettäväksi OTP-kertakäyttösalasanoilla! Valitse tietokanta ensin. OTP hylätään turvallisuussyistä. - Kertakäyttösalasana hylätty: Kaikki salasanat on jo käytetty! + Salasana hylätty: Kaikki salasanat on jo käytetty! Sulje ensin tietokanta. OTP hylätään. (Yksi tai useampi OTPs on jo saatavilla) OTP salaus (esimerkiksi 01 23 ab cd...) - Virhe OTP-salaisuuden jäsentämisessä! + Virhe OTP-salauksen jäsentämisessä! OTP-avaimen luominen epäonnistui! Varmista, että OTP:t on syötetty oikein. Virhe OTP-lisätiedoston päivityksessä! Tallennetaan OTP-lisätiedostoa… - Haaste-vastaus on virheellinen. - Ei voitu ladata haastetiedostoa! - Käytä KeeChallenge-liitännäistä KeePass 2.x (PC) ja määritä tietokanta käyttämään haasteeseen vastaamista! + Vaadittu vastaus on virheellinen. + Ei voitu ladata tiedostoa! + Käytä KeeChallenge-liitännäistä KeePass 2.x (PC) ja määritä tietokanta käyttämään vaadittua vastausta! Virhe päivitettäessä OTP-lisätiedostoa! - TOTP-siemenkentän nimi + TOTP-Siemenkentän nimi Jos et käytä Keepass 2 \"TrayTotp\" liitännäisen oletusasetuksia, kirjoita siemenkentän nimi PC-version asetusten mukaisesti. - TOTP-asetuksien kentän nimi + TOTP-Asetuksien kentän nimi Syötä TrayTotp:n asetukset sisältävän kentän nimi tähän. TrayTotp Ladataan… @@ -448,7 +451,7 @@ Valitsemallasi tiedostolla on vain lukuoikeudet. Valitsemallasi tiedostolla Keepass2Android on vain lukuoikeudet , koska Android 4.4 +:ssa on rajoituksia. Käyttääksesi sitä se pitää kopioida toiseen paikkaan. - Jos muokkaat sitä niin kopioi Tiedosto toiseen hakemistöön. + Jos muokkaat sitä niin kopioi Tiedosto toiseen hakemistoon. Klikkaa OK valitaksesi sijainnin, johon tiedosto kopioidaan. Peruuta, avaa vain luku-tilassa. Kopioin tiedostoa... @@ -512,9 +515,9 @@ Versio 0.9.6\n Vain salasana Salasana + Avaintiedosto Salasana + OTP - Salasana + OTP salaus (recovery mode) - Salasana + Challenge-Respons - Salasana + Challenge-Response salaus (recovery mode) + Salasana + OTP salaus (Palautustila) + Salasana + Vastausvaatimus + Salasana + Vastausvaatimus salaukseen (palautustila) Ohita varmenteiden virheet diff --git a/src/keepass2android/Resources/values-fr/strings.xml b/src/keepass2android/Resources/values-fr/strings.xml index 7dd46b68..8a4c652b 100644 --- a/src/keepass2android/Resources/values-fr/strings.xml +++ b/src/keepass2android/Resources/values-fr/strings.xml @@ -65,6 +65,7 @@ Chiffres Keepass2Android n\'offre ABSOLUMENT AUCUNE GARANTIE ; il s\'agit d\'un logiciel gratuit, et vous pouvez le redistribuer sous les conditions de la licenceGPL v2 ou ultérieure. \u2026 + Copier dans le Presse-papier Entrez le nom de fichier de la base de données Accédé Annuler diff --git a/src/keepass2android/Resources/values-it/strings.xml b/src/keepass2android/Resources/values-it/strings.xml index 5f469b5d..ca5419f9 100644 --- a/src/keepass2android/Resources/values-it/strings.xml +++ b/src/keepass2android/Resources/values-it/strings.xml @@ -65,6 +65,7 @@ Cifre Keepass2Android viene distribuito ASSOLUTAMENTE SENZA ALCUNA GARANZIA; Si tratta di software libero e sei invitato a distribuirlo sotto le condizioni della licenza GPL versione 2 o superiore. \u2026 + Copia negli appunti Inserisci il nome del file del database Ultimo accesso Annulla diff --git a/src/keepass2android/Resources/values-ja/strings.xml b/src/keepass2android/Resources/values-ja/strings.xml index 118cc7e3..9ab37ceb 100644 --- a/src/keepass2android/Resources/values-ja/strings.xml +++ b/src/keepass2android/Resources/values-ja/strings.xml @@ -65,6 +65,7 @@ 数字 Keepass2Android によって作られたフリーソフトウェアであり、無保証です。GPLバージョン2以上の条件下でこれを再頒布することができます。 \u2026 + クリップボードにコピー データベースファイル名の入力 最終アクセス日 キャンセル diff --git a/src/keepass2android/Resources/values-nb/strings.xml b/src/keepass2android/Resources/values-nb/strings.xml index 36ca3c61..2277977b 100644 --- a/src/keepass2android/Resources/values-nb/strings.xml +++ b/src/keepass2android/Resources/values-nb/strings.xml @@ -7,7 +7,7 @@ Keepass2Android er en android-utgave av KeePass passordbestyrer. Brukergrensesnittet er basert på en port av KeepassDroid utviklet av Brian Pellin. Kildekode til databaseoperasjoner er basert på KeePass av Dominik Reichl. Android roboten, laget og delt av Google, er reprodusert og modifisert i henhold til Creative Commons 3.0 Navngivelse Lisensen. Godta - Legg til post + Legg til oppføring Lag oppføring for URL Legg til gruppe Legg til gruppe diff --git a/src/keepass2android/Resources/values-nl/strings.xml b/src/keepass2android/Resources/values-nl/strings.xml index ce44142d..ae97d8b1 100644 --- a/src/keepass2android/Resources/values-nl/strings.xml +++ b/src/keepass2android/Resources/values-nl/strings.xml @@ -65,6 +65,7 @@ Cijfers Keepass2Android biedt GEEN ENKELE GARANTIE; Dit is gratis software, u mag deze software verspreiden onder de voorwaarden van de GPL versie 2 of recenter. \u2026 + Kopieer_naar_klembord Voer databasebestandsnaam in Benaderd Annuleren diff --git a/src/keepass2android/Resources/values-pl/strings.xml b/src/keepass2android/Resources/values-pl/strings.xml index 7daf2151..efaa8dfa 100644 --- a/src/keepass2android/Resources/values-pl/strings.xml +++ b/src/keepass2android/Resources/values-pl/strings.xml @@ -65,6 +65,7 @@ Cyfry Keepass2Android jest udostępniany BEZ JAKIEJKOLWIEK GWARANCJI. Niniejszy program jest wolnym oprogramowaniem: możesz go swobodnie rozpowszechniać na warunkach licencji GNU General Public License w wersji 2 lub późniejszej. \u2026 + Kopiuj do schowka Wprowadź nazwę pliku bazy danych Ostatni dostęp Anuluj diff --git a/src/keepass2android/Resources/values-pt-rPT/strings.xml b/src/keepass2android/Resources/values-pt-rPT/strings.xml index 93926a9e..5ab2db89 100644 --- a/src/keepass2android/Resources/values-pt-rPT/strings.xml +++ b/src/keepass2android/Resources/values-pt-rPT/strings.xml @@ -46,6 +46,8 @@ Muito útil se existirem muitos resultados iguais. Apenas disponível para ficheiros locais. Ficheiro guardado na pasta local. A base de dados foi copiada para a pasta local. Prima OK para abrir a nova localização. Nota: Não se esqueça de exportar a sua base de dados para uma localização segura regularmente! + O ficheiro-chave foi copiado para a directoria interna. Verifique se tem uma cópia de seguranca válida antes de a eliminar da directoria actual! + Não é possível usar a directoria interna quando a localização do ficheiro-chave não é guardada. Altere as preferências de segurança. Parêntesis Cancelar Área de transferência limpa. @@ -54,6 +56,7 @@ Muito útil se existirem muitos resultados iguais. Copiar usuário para a área de transferência Copiar senha para a área de transferência Entrada está disponível através do teclado KP2A + está disponível Não foi possível abrir a caixa de diálogo para selecionar o método de entrada. Por favor, ative o teclado manualmente. Por favor habilite o teclado Keepass2Android nas configurações do sistema. Criando a chave da base de dados… @@ -63,6 +66,7 @@ Muito útil se existirem muitos resultados iguais. Dígitos O Keepass2Android vem ABSOLUTAMENTE SEM GARANTIA; Este software é gratuito, e todos podem distribuí-lo de acordo com as condições do GPL versão 2 ou mais recente. \u2026 + Copiar para a área de transferencia Introduza o nome do arquivo da base de dados Acessado Cancelar @@ -74,6 +78,7 @@ Muito útil se existirem muitos resultados iguais. Expira Nome do Grupo Arquivo de chave (opcional) + Ficheiro-chave Modificado Senha Salvar @@ -86,6 +91,7 @@ Muito útil se existirem muitos resultados iguais. Erro ao criar o grupo. Não foi possível criar o diretório \'pai\'. Este arquivo já existe. + Falha ao determinar as configurações da base de dados. Falha ao executar link. É necessário um nome de arquivo. Não foi possível criar o ficheiro @@ -119,6 +125,7 @@ Muito útil se existirem muitos resultados iguais. Algoritmo inválido. Formato da base de dados não foi reconhecido. Ficheiro-chave não existe. + Nenhum ficheiro-chave seleccionado. Ficheiro-chave está vazio. Tamanho Tamanho da lista de grupos @@ -137,6 +144,8 @@ Muito útil se existirem muitos resultados iguais. Configurações da base de dados Apagar Mover para outro grupo + Mover + Ir para grupo parente Doe uma cerveja... Editar Esconder palavra-passe @@ -151,7 +160,11 @@ Muito útil se existirem muitos resultados iguais. Nunca Sim Não + Não há registos na base de dados ou grupo. Não há resultados de pesquisa + Nenhum programa compativel com esta url. + Abrir a base de dados recente (clique para abrir) + Não pesquisar registos nas cópias de segurança e na lixeira A processar… Remover Rijndael (AES) @@ -217,6 +230,10 @@ Muito útil se existirem muitos resultados iguais. Nome do Campo Valor do campo Campo protegido + Anexar ficheiro... + Adicionar outro texto + Eliminar texto adicional + %1$s: Bloqueado. Desbloqueamento rápido activo. %1$s: Desbloqueado. Introduza as credenciais do servidor Bloquear quando o ecrã se desligar @@ -232,6 +249,7 @@ Muito útil se existirem muitos resultados iguais. Reciclagem Deseja apagar esta entrada permanentemente? Pressione Não para reciclar. Apagar permanentemente? + Recarregar ficheiro? Descartar alterações? Sugerir ou votar melhorias Classifique esta aplicação @@ -263,6 +281,21 @@ Muito útil se existirem muitos resultados iguais. porta Insira os dados de login SFTP: Ficheiro local + Dropbox + Ficheiro-chave + Utilizar ficheiro-chave + TOTP Configurações - Nome do campo + Escreva o nome do campo de configuração da extensão TrayTotp aqui. + TrayTotp + A Carregar… + Extensões + Nome do pacote: + Descrição (não verificada): + Autor (não verificado): + activo + inactivo + Encontrar plug-ins on-line + Contexto 30 segundos 1 minuto diff --git a/src/keepass2android/Resources/values-ro/strings.xml b/src/keepass2android/Resources/values-ro/strings.xml index 24a70454..084e9ef6 100644 --- a/src/keepass2android/Resources/values-ro/strings.xml +++ b/src/keepass2android/Resources/values-ro/strings.xml @@ -4,14 +4,16 @@ Feedback Start - Keepass2Android este un manager de parole ce ofera acces citire/scriere la baze de date KeePass 2.x sub Android. + Keepass2Android este un manager de parole ce oferă citire/scriere la baze de date KeePass 2.x pe Android. Interfaţa cu utilizatorul este bazată pe un port al KeepassDroid dezvoltat de Brian Pellin. Codul pentru operaţiunile cu baza de date este bazat pe KeePass de Dominik Reichl. Robotul Android este reprodus sau modificate din materiale create şi împărtăşite de Google şi utilizate în conformitate cu condiţiile descrise de licenţa Creative Commons Attribution 3.0. + Suportul pentru SFTP este implementat folosind librăria JSch sub licență BDS, creată de JCraft, Inc. Accepta - Adăugaţi o înregistrare - Creaţi intrarea pentru URL - Adăugare grup + Interzice + Adăugă o înregistrare + Creaţi înregistrare pentru URL + Adăugă un grup Adăugare grup - Editează Grup + Editează Grupul Algoritm Algoritm Keepass2Android @@ -20,13 +22,31 @@ KP2A Offline Expirare aplicație Timp înainte de blocarea bazei de date atunci când aplicația este inactivă. + Oprește aplicația + Buton de închidere + Afișează un buton pentru închiderea aplicației în ecranul cu parole (pentru useri paranoici) Aplicația Setări aplicație + Arată numele grupului în rezultatele căutării + Arată numele grupului sub titlul înregistrărilor în rezultatele căutării. Folositor dacă mai multe înregistrări au același nume. + Grupul afișat este acum: %1$s + Arată numele grupului în vizualizarea înregistrărilor + Scuze! Keepass2Android nu poate interpreta URI-ul returnat %1$s. Te rog să contactezi producătorul! Securitate Afişare Acces introducere parolă QuickUnlock - Tratare fişiere + Utilizare fişiere + Tastatură + Exportă baza de date... + Importă baza de date în folderul intern + Importă fișierul cheie în folderul intern + Comutare tastaturi + Valabil doar pentru fișiere locale. + Fișierul este stocat în folderul intern. + Baza de date a fost copiată în folderul intern. Apasă Ok pentru a o deschide din noua locație. Notă: Nu uita să exporți periodic baza de date pe un spațiu de stocare sigur! + Fișierul-cheie a fost copiat în folderul intern. Asigură-te că ai o copie de rezervă înainte de al șterge din locația curentă! + Imposibil de folosit folderul intern când locația fișierului cheie nu este memorară. Schimbă preferințele de securitate. Paranteze Anulează Clipboard golit. @@ -35,15 +55,17 @@ Selectați pentru a copia utilizatorul în clipboard Selectați pentru a copia parola în clipboard Înregistrarea este disponibilă folosind tastatura KP2A + este disponibil Nu s-a putut deschide dialogul de a selecta medoda de introducere. Activați tastatura manual. - Activați tastatura Keepass2Android în setarile dvs. de sistem. - Se crează cheia bazei de date… + Activați tastatura Keepass2Android în setările dvs. de sistem. + Se creează cheia bazei de date… Grup curent - Grup curent: root + Grup curent: Root Baza de date Cifre Keepass2Android este oferit FĂRĂ NICI O GARANȚIE; Acesta este software gratuit și sunteți bine venit să îl redistribuiți respectând condițiile GPL versiunea 2 sau mai nouă. \u2026 + Copiază în clipboard Alegeți numele bazei de date Accesat Anulează @@ -53,32 +75,35 @@ Confirmă parola Creat Expiră + Nume Grup Fişierul cheie (opţional) + Fișier cheie Modificat Parola Salvează Nume URL Nume de utilizator - Cămpuri string suplimentare + Câmpuri text suplimentare Fișiere atașate Keepass2Android nu poate utiliza acest uri. Eroare creare grup. - Imposibil de creat directorul părinte. + Imposibil de creat folder-ul părinte. Acest fișier există deja. + Nu s-au putut determina setările bazei de date. Nu s-a putut lansa link-ul. Este necesar un nume fișier. Nu s-a putut crea fișierul Bază de date invalidă. - Path invalid. + Cale invalidă. Este necesar un nume. Este necesară o parolă sau un fișier cheie. - Trebuie selectat cel puțin un timp de generare de parole + Trebuie selectat cel puțin un tip de generare de parole Parolele nu se potrivesc. Etapele trebuie să fie un număr. Este necesar un titlu. Introduceți un număr întreg pozitiv pentru lungimea câmpului - Fișierul s-a găsit. + Fișierul nu s-a găsit. Browser fișiere Generare parolă Grup @@ -91,14 +116,15 @@ parola Parola nume - URL - rescrie URL-ul + url + rescrie url-ul tag1, tag2 nume de utilizator Parolă sau fișier cheie invalide. Algoritm invalid. Formatul bazei de date nu este cunoscut. Fișierul cheie nu există. + Nici un fișier cheie selectat. Fișierul cheie este gol. Lungime Dimensiune listă grupuri @@ -106,7 +132,7 @@ Se încarcă baza de date… Litere mici ***** - Mascare parolă + Maschează parola Ascunde parolele în mod implicit Despre Schimbă cheia principală @@ -114,10 +140,12 @@ Copiază nume utilizator Crează Setări - Setări baze de date + Setări bază de date Şterge Muta într-un alt grup - Doneaza o bere... + Mută + Navighează la grupul părinte + Donează o bere... Editare Ascunde parola Blochează baza de date @@ -135,31 +163,37 @@ Nici un rezultat de căutare Nici o rutină de tratare a acestui url. Deschideţi baza de date recentă (click pentru a deschide) - Nu cauta înregistrări în backup şi coşul de gunoi + Nu căuta înregistrări în backup şi coşul de gunoi Omite grupurile \'Backup\' şi \'Coş de gunoi\' din toate căutările Nume fişier bază de date KeePass Introduceţi parola bazei de date + Selectează tipul cheii principale: Se creează baza de date nouă… Creare bază de date - Procesează… + Se procesează… Reţine locaţia fişierului cheie Salvează fișierul cheie Elimină Rijndael (AES) Root Etape de criptare - Mai multe etape de criptare oferă protecţie împotriva atacurilor brute, dar pot încetini semnificativ încărcarea şi salvarea. + Mai multe etape de criptare oferă protecţie împotriva atacurilor prin forță brută, dar pot încetini semnificativ încărcarea şi salvarea. etape Numele bazei de date Nume utilizator implicit pentru intrări noi - Salvez baza de date… + Se salvează baza de date… + Se exportă baza de date… + Baza de date exportată cu succes! Spaţiu Căutare Arată parola - Sorteaza dupa nume - Sortează după data creeării + Sortează după... + Sortează după nume + Sortează după data creării + Sortează după data modificării + Păstrează ordinea implicită Special - Găsește ce + Găsește Rezultate căutare Căutare în Selectaţi o altă înregistrare @@ -171,90 +205,122 @@ Litere mari Cardul sd este momentan read-only. Nu veți putea salva modificările la baza de date. Cardul sd nu este montat momentan. Nu veți putea încărca sau crea baza de date. - Versiunea + Versiune Istoric versiuni - Keepass2Android este dezvoltat de către Philipp Crocoll. - Vă mulţumim pentru contribuţiile cod %1$s. - Plugin-ul pentru cifrul Twofish a fost dezvoltat de Scott Greenberg şi este inclus în KP2A. - Android-filechooser a fost dezvoltat de Hai Bison + Keepass2Android este creat de către Philipp Crocoll. + Mulțumită contribuţiilor de cod de către %1$s. + Icoană și design mulțumită contribuțiilor făcute de %1$s. + Plugin-ul pentru cifrul Twofish a fost creat de Scott Greenberg şi este inclus în KP2A. + android-filechooser a fost creat de Hai Bison + Tastatura KP2A este bazată pe tastatura Gingerbread din Android Open Source Project și folosește codul Plugin Manager din Hacker\'s Keyboard creat de Klaus Weidner. Vă rugăm să reţineţi Contribuitori Regular expression Tan expiră la utilizare Marchează înregistrările TAN ca expirate la utilizarea lor - Afişeayă numele utilizator în lista - Afişează numele utilizator sub înregistrări. Util pentru conturi sau TAN-uri multiple. - Reţine baza de date + Afişează numele utilizatorului în listă + Afişează numele utilizatorului sub înregistrări. Util pentru conturi sau TAN-uri multiple. + Reţine bazele de date Reţine baze de date deschise recent si afişează-le în ecranul de deschidere a bazelor de date. - Keepass2Android: Cautare parolă + Keepass2Android: Căutare parolă Exclude înregistrările expirate Opţiuni - Diferenţiere între minuscule şi majuscule + Case sensitive Deschide fişier... Creează bază de date nouă... Deschide URL... Importă fişier în bază de date nouă... Trebuie specificat URL-ul complet inclusiv protocolul, de exemplu http://. - Fişierul de importat trebuie selectat în la pasul următor. + Fişierul de importat va fi selectat la pasul următor. Activare QuickUnlock Introduceţi ultimele %1$d caractere ale parolei dvs.: QuickUnlock! Închide baza de date - Permite QuickUnlock implicit + Activează QuickUnlock implicit Defineşte dacă QuickUnlock este activat implicit sau nu. + Protejează afișajul bazei de date + Dacă este activat, captura ecranului nu este permisă și nici o pictogramă a aplicației nu va fi afișată în lista cu Aplicații Recente. Ascunde icoana QuickUnlock QuickUnlock nu funcţionează din păcate fără a afişa o icoană de notificare. Selectaţi această opţiune pentru a utiliza o icoană transparentă. + Ascunde icoana QuickUnlock + QuickUnlock necesită o notificare pentru a funcționa corect. Selectează această opțiune pentru a afișa o notificare fără icoană. Lungimea cheii QuickUnlock Numărul maxim de caractere utilizate ca şi parolă QuickUnlock. QuickUnlock a eşuat: parolă incorectă! - Director ataşamente - Director unde se salvează ataşamentele. + Folder ataşamente + Folder în care se salvează ataşamentele. Salvaţi ataşament Selectaţi unde se salvează ataşamentul. Salvaţi pe cardul SD Salvează în cache și deschide Fișierul salvat ca %1$s. Nu s-a putut salva atașamentul la %1$s. + Memorează textul căutat? + Doriți să adăugați textul căutat \"%1$s\" la înregistrarea selectată pentru a o găsi automat următoarea dată? Format dată/timp invalid pentru data expirării! Este necesar un nume câmp pentru fiecare string. Numele câmpului Valoarea câmpului Câmp protejat Ataşează fişier... - Adaugă string adiţional - Şterge string adiţional - %1$s: blocat. QuickUnlock activat. - %1$s: deblocat. - Introduceți datele conectare la server + Adaugă câmp adiţional + Şterge câmp adiţional + %1$s: Blocat. QuickUnlock activat. + %1$s: Deblocat. + Introduceți datele de conectare la server Tranzacții fișier Foloseşte tranzacţii pentru a scrie bazele de date + Blochează când ecranul este stins + Blochează baza de date atunci când ecranul este stins. + Șterge parola principală introdusă + Șterge parola principală introdusă când părăsiți ecranul fără să deblocați baza de date. + Blochează când părăsiți aplicația + Blochează baza de date când părăsiți aplicația apăsând butonul înapoi. + Ascunde opțiunea de donație + Această setare este pentru donatori. Este valabilă doar după ce folosiți Keepass2Android o vreme. + Fără donații, această aplicație nu ar exista și nu ar fi îmbunătățită continuu! Dacă nu ai donat încă, te invităm să faci o donație acum. Caching bază de date - Păstrează o copie a bazelor de date remote în directorul cache. Aceasta vă permite să le utilizaţi şi offline. - Goliţi Cache-ul? + Păstrează o copie a bazelor de date remote în folderul cache. Aceasta vă permite să le utilizaţi şi offline. + Certificate SSL + Definește comportamentul atunci când validarea certificatului eșuează. Notă: puteţi instala certificate pe aparatul vostru dacă validarea eşuează! + Goliţi cache-ul? Aceasta va şterge toate bazele de date din cache. Orice modificări făcute offline ce nu au fost sincronizate vor fi pierdute! Continuaţi? Verifică modificări Verifică dacă nu s-a modificat extern fişierul înainte de a salva. + Verifică dubluri UUID + Verifică dacă fişierul bazei de date este corupt având mai multe înregistrări cu acelaşi ID. Acest lucru poate cauza un comportament neaşteptat. Notificări clipboard - Oferă utilizatorul şi parolă folosind bara de notificări şi clipboard-ul. Atenţie la \"password sniffers\"! + Oferă utilizatorul şi parolă prin bara de notificări şi clipboard. Atenţie la \"password sniffers\"! + Separă notificările + Arată notificări separate pentru copierea numelui utilizatorului și a parolei în clipboard și activarea tastaturii. Notificare tastatură KP2A Oferă întreaga înregistrare folosind tastatura KP2A (recomandat). - Afişează o notificare \"în curs\" în timp ce baza de date este deblocată. - Pre-încărca fişierul bază de date - Începe încărcarea în fundal sau descărcarea de la distanţă în timp ce se introduce parola. + Comută tastatura + Deschide fereastra de selecție a tastaturii când o înregistrare este disponibilă prin tastatura KP2A după căutarea din browser. + Comută automat dacă e rootat + Comută automat la tastatura KP2A când o înregistrare este disponibilă. Necesită un telefon rootat și aplicația Secure Settings cu System+. + Comută automat tastatura doar după căutare + Comută automat la tastatura KP2A doar după utilizarea funcției Share URL (și nu când se deschide o înregistrare în alt fel) + Comutare înapoi la tastatură + Comută la tastatura precedentă când nici o înregistrare este deschisă. + Notificare cât timp e deblocat + Afişează o notificare în timp ce baza de date este deblocată. + Pre-încarcă fişierul bază de date + Începe încărcarea sau descărcarea în fundal în timp ce se introduce parola. Doriţi să suprascrieţi binarul existent folosind acelaşi nume? Suprascrieţi binarul existent? Suprascrie Redenumește Eroare la adăugarea ataşamentului. - Recycle Bin + Coș de gunoi Doriţi să ştergeţi permanent această înregistrare? Apăsaţi Nu pentru a muta în coş. - Doriţi să ştergeţi permanent acest grup? Apăsaţi Nu pentru a muta la coş. + Doriţi să ştergeţi permanent acest grup? Apăsaţi Nu pentru a muta în coş. Ștergeți definitiv? Reîncărcaţi fişierul? Fişierul deschis a fost modificat de alt program. Doriţi să îl reîncărcaţi? - Doriţi să renunţaţi la modificările făcute? (Butonul save este în partea superioară a formularului.) - Renunta la modificari? + Doriţi să renunţaţi la modificările făcute? (Butonul de salvare este în partea superioară a formularului.) + Renunță la modificări? Propuneți sau votați pentru îmbunătățiri Evaluează această aplicație Traduce KP2A @@ -268,10 +334,10 @@ Se decodează baza de date… Se parsează baza de date… Se verifică fişierul ţintă pentru modificări… - Combinare modificări? - Fişierul bazei de date a fost modificat extern. Doriţi să încărcaţi şi să combinaţi modificările înainte de salvare. Selectaţi Nu dacă doriţi să suprascrieţi modificările externe. - Se combină modificările… - Da, combină + Îmbinare modificări? + Fişierul bazei de date a fost modificat extern. Doriţi să încărcaţi şi să îmbinați modificările înainte de salvare. Selectaţi Nu dacă doriţi să suprascrieţi modificările externe. + Se îmbină modificările… + Da, îmbină Nu, suprascrie Sincronizează baza de date din cache… Se descarcă fişierul de la distanţă… @@ -279,19 +345,33 @@ Se restaurează fişierul de la distanţă… Fişierele sunt sincronizate. Baza de date s-a sincronizat cu succes! - Verific baza de date pentru modificări… + Se verifică baza de date pentru modificări… Nu s-a putut salva la distanţă: %1$s. Salvaţi din nou sau folosiţi meniul Sincronizare atunci când conexiunea revine. Nu s-a putut deschide de la distanţă: %1$s. S-a încărcat versiunea locală. Totuşi puteţi face modificări în baza de date şi să le sincronizaţi ulterior. S-a actualizat fişierul remote. - S-a deschis varianta locală din cauza unor conflicte cu varianta remote. Folosiţi meniul Sincronizare pentru a combina. - Varianta remote şi din cache sun sincronizate. + S-a deschis varianta locală din cauza unor conflicte cu varianta remote. Folosiţi meniul Sincronizare pentru a îmbina. + Varianta remote şi cache sunt sincronizate. + S-a actualizat copia locală %1$s. Nu s-au detectat modificări. + S-a actualizat fișierul auxiliar OTP din cache: Contorul remote era mai mare. + S-a actualizat fișierul auxiliar OTP remote: Contorul local era mai mare. + Se sincronizează fișierul auxiliar OTP… + fișier bază de date + Fişier auxiliar OTP A apărut o eroare: + Baza de date este coruptă: ID-uri duplicate au fost găsite. (Ai salvat cu Minikeepass?) Te rog să reimporți o bază de date nouă cu Keepass 2 pentru PC selectând \'Create new IDs\'. + Poți dezactiva acest mesaj în Setări/Setări aplicație/Utilizare fişiere/Verifică dubluri UUID. Reține că este posibil ca aplicația să se comporte neașteptat. Este recomandat pentru a repara baza de date. Sincronizează baza de date… Nu se poate muta grupul în acest grup. Astăzi este Oktoberfest! Dacă vă place Keepass2Android: nu ar fi azi o zi potrivită să-mi cumpăraţi o bere? + 10 mai? Este ziua mea! Dacă îți place această aplicație, de ce să nu-mi trimiți niște felicitări împreună cu un mic cadou? Asta mă va face foarte fericit! :-) + Oh, ai pierdut ziua mea de naștere pe 10 mai! Dacă îți place această aplicație, de ce să nu-mi trimiți niște felicitări împreună cu un mic cadou? Încă nu e prea târziu să fiu fericit! :-) Spune-mi mai multe! Nu, nu-mi place atât de mult + host (ex: 192.168.0.1) + port + Folder inițial (opțional): + Introduceţi datele de conectare SFTP: Selectaţi tipul de stocare: Fişier local Obţine de la aplicaţie externă @@ -300,44 +380,184 @@ HTTP (WebDav) HTTPS (WebDav) Dropbox + Dropbox (folder KP2A) + Dacă nu doriți să oferiți KP2A acces la tot Dropbox-ul, poți selecta această opțiune. Aceasta va solicita acces doar la folderul Apps/Keepass2Android. Acest lucru este ideal când creați o bază de date nouă. Dacă ai deja o bază de date, apasă această opțiune pentru a crea folderul, puneți baza de date în folder (de pe PC) apoi selectați opțiunea aceasta din nou pentru a deschide fișierul. Google Drive - Iniţializere access fişier + OneDrive + SFTP (SSH File Transfer) + Iniţializare acces fişier Locaţie bază de date Puteţi stoca baza de date local pe aparatul dvs. sau în cloud (versiunea non-Offline). Keepass2Android face baza de date disponibilă şi dacă sunteţi offline. Deoarece baza de date este criptată AES 256 bit nimeni nu va putea accesa parolele dvs. Vă recomandăm Dropbox: este accesibil pe toate aparatele dvs. şi oferă chiar copii de siguranţă a versiunilor anterioare ale unui fişier. Selectaţi unde doriţi să stocaţi baza de date: Modifică locaţia Parola principală Baza de date este criptata cu parola ce o introduceţi aici. Alegeţi o parolă puternică pentru a păstra datele în siguranţă! Sfat: Inventaţi o propoziţie sau două si folosiţi prima literă a cuvintelor. Includeţi şi semnele de punctuaţie. - Alegeţi o parolă master pentru a proteja baza de date: + Alegeţi o parolă principală pentru a proteja baza de date: Fişier cheie - Un fişier cheie este în esenţă o parolă stocate într-un fişier. Fişierele cheie sunt de obicei mai puternice decât parola master, deoarece cheia poate fi mult mai complicată; cu toate acestea este, de asemenea, mai greu să o ţineţi secretă. Dacă stocați bazei de date în cloud, nu păstraţi şi cheia tot acolo! Acest lucru ar fi complet inutil! Important: Nu modificaţi conţinutul fişierului cheie după crearea bazei de date! - Alegeţi dacă doriţi să utilizaţi un fişier cheie pe lângă parola de master: + Un fişier cheie este în esenţă o parolă stocată într-un fişier. Fişierele cheie sunt de obicei mai puternice decât parola principală, deoarece cheia poate fi mult mai complicată; cu toate acestea este, de asemenea, mai greu să o ţineţi secretă. Dacă stocați baza de date în cloud, nu păstraţi şi cheia tot acolo! Acest lucru ar fi complet inutil! Important: Nu modificaţi conţinutul fişierului cheie după crearea bazei de date! + Alegeţi dacă doriţi să utilizaţi un fişier cheie pe lângă parola principală: Foloseşte fişier cheie Eroare la adăugarea fişierului cheie! - Change log + Se încarcă fișierul auxiliar OTP… + Introduceți următorul One-time-passwords (OTP). Puneți Youbikey NEO-ul vostru pe spatele aparatului pentru a introduce prin NFC. + OTP %1$d + Nu s-a găsit o aplicație care să se ocupe de această provocare. Te rog să instalezi Yubichallenge de pe Google Play. + Nu se poate încărca fișierul auxiliar OTP! + Te rugăm să folosești plugin-ul OtpKeyProv în KeePass 2.x (PC) pentru a configura baza de date pentru OTP-uri! + Te rugăm să selectezi baza de date întâi. OTP este ignorat pentru motive de securitate. + OTP ignorat: Toate OTP-urile au fost deja introduse! + Te rugăm să închizi baza de date întâi. OTP este ignorat. + (Unul sau mai multe OTP -uri sunt deja disponibile) + Secret OTP (ex. 01 23 ab cd…) + Eroare în citire secret OTP! + Imposibil de creat cheia OTP! Asigură-te că ai introdus OTP-urile corecte. + Eroare în actualizare fișier auxiliar OTP! + Se salvează fișierul auxiliar OTP… + Răspunsul la provocare este incorect. + Nu se poate încărca fișierul auxiliar de provocare! + Vă rugăm să folosiți plugin-ul KeeChallenge în KeePass 2,x (PC) pentru a configura data de baze cu răspunsuri-provocare! + Eroare în actualizare fișier auxiliar OTP! + Nume câmp seed TOTP + Dacă utilizaţi plugin-ul Keepass 2 \"TrayTotp\" cu setări non-implicite, introduceţi numele de câmp pentru câmpul de seed aici în funcţie de setările de pe PC. + Nume câmp setări TOTP + Introduceţi aici numele de câmp al câmpului de setări pentru TrayTotp. + TrayTotp + Se încarcă… + Plugin-uri + Numele pachetului: + Descriere (neverificată): + Autor (neverificat): + activat + dezactivat + Caută plugin-uri online + Domenii + %1$s solicită date de login pentru %2$s. + %1$s solicită date de login. Selectează o înregistrare. + Activat + Notificare acțiune bază de date + Plugin-ul va fi notificat când o bază de date este deschisă, închisă sau salvată. + Date înregistrare curentă + Plugin-ul va primi toate datele despre înregistrarea curentă din baza de date şi va putea oferii acţiuni şi modifica afişarea acesteia. + Interoghează propriile date de login + Plugin-ul va putea interoga datele de login asociate cu propriul său pachet de aplicație. + Interoghează datele de login + Plugin-ul va putea interoga datele de login pentru site-uri sau aplicații deliberate. + Obțineți mai multe tipuri de stocare + Atenție: Validarea certificatului de server a eșuat: %1$s. Instalați pe aparat certificatul root corespunzător sau vedeți setările! + Eroare: Validarea certificatului de server a eșuat! Instalați pe aparat certificatul root corespunzător sau vedeți setările! + Selectează formatul fișierului + Ne pare rău! Keepass2Android a fost oprit de Android OS! Din motive de securitate, Keepass2Android nu a menținut datele de login selectate pe disk, deci va trebui să redeschideți baza de date. Notă: Aceasta ar trebui să se întâmple foarte rar. În caz contrar, te rog să îmi lași un mesaj la crocoapps@gmail.com. + Fișierul este disponibil temporar pentru Keepass2Android. + Fişierul selectat este read-only. + Fișierul selectat este read-only pentru Keepass2Android din cauza restricțiilor pe Android 4.4+. + Pentru a-l folosi, trebuie copiat într-o altă locație. + Pentru a-l edita, trebuie copiat fișierul într-o altă locație. + Apasă pe OK pentru a selecta locația în care se va copia fișierul. + Anulați, deschideți read-only. + Se copiază fișierul... + Vă rugăm să reţineţi: aţi încărcat o bază de date Keepass 1. Keepass2Android a adăugat recent suport pentru scrierea în acest format de bază de date. În ciuda testărilor riguroase, autorul nu garantează că toate datele vor fi salvate corect. Vă rugăm să păstraţi întotdeauna o copie de rezervă a bazei de date originale (Dropbox stochează automat versiunile recente) înainte de a face modificări. Vă rugăm să raportaţi orice probleme. Mulţumesc! + Jurnal modificări + Rețineți! Aceasta este o versiune de examinare și poate avea unele defecte! Dacă vă confruntați cu *ceva* neașteptat, vă rog să îmi spuneți (pe Codeplex sau prin email). + +Versiunea 0.9.7\n +* suport pentru scrierea bazelor de date Keepass 1 (kdb) (beta)!\n +* trecerea la tastatura anterioară mai bună (de asemenea, funcţionează pe dispozitivele fără root)\n +* suport pentru KeeChallenge cu provocări de lungime variabilă\n +* împiedică screenshot-urile la QuickUnlock si parolă\n +* s-a inversat ordinea de sortare pentru Sortează după data modificării (acum descrescătoare)\n +* bug rezolvat: Notele se actualizează acum corect după modificări, parola se ascunde corect pe (sperăm) toate dispozitivele, rezolvat problema care a permis să se adauge o înregistrare de două ori, rezolvat problema cu afișarea avertizării pentru UUID-uri duplicate chiar după corectarea bazei de date\n + +Versiunea 0.9.6\n +* permite să se importe fișierul cheie și/sau fişierul bazei de date în folderul intern (a se vedea setările)\n +* permite diferite opțiuni de sortare\n +* îmbunătăţit preferinţele pentru comutarea automată a tastaturii\n +* actualizat logo-ul aplicației şi design-ul notificării, design de Stefano Pignataro (http://www.spstudio.at)\n +* generatorul de parola reține ultimele setări\n +* setaţi vizibilitatea notificării pentru ecranul de blocare Android 5\n +* acum se șterge câmpul cu parola principală când se părăsește aplicația fără a apăsa OK\n +* rezolvat problemă cu lipsa unor limbi în setările tastaturii pe unele aparate\n +* rezolvat problemă la comutarea automată a tastaturii pe aparate cu root\n +* adăugat verificare pentru baze de date corupte (UUID-uri duplicate)\n +* reîncarcă automat baza de date atunci când au fost detectate schimbări, rezolvă o problemă de securitate privind dezvăluirea parolei principale\n +* îmbunătăţit schema tastaturii mici, rezolvat tema setărilor tastaturii (mulțumită lui Wiktor Ławski)\n + +Versiunea 0.9.5\n +* Rezolvat probleme cu navigarea fisierelor (mai ales pe Android 4.4)\n +* Rezolvat problemă cu încărcarea fişierelor .kdb (Keepass 1) pe Nexus 5 cu Android Lollipop\n +* Adăugat opţiunea de a preveni screenshot-uri/afişarea în lista cu aplicații recente\n +* Rezolvat problemă cu stocarea Google Drive (ediția obișnuită)\n +* Permite fişierele cheie pe tipuri de stocare deliberate (ediția obișnuită)\n +* Actualizat Dropbox SDK pentru a include un patch oficial de securitate (ediția obișnuită)\n +* Actualizat utilitarele --> dimensiunea apk-ului a crescut :-(\n +Am promis mai multe modificări. Vor veni cu următoarea versiune - scuze. Am vrut să public aceste remedieri cât mai repede posibil. + +Versiunea 0.9.4\n +* adăugat suport pentru plug-in: consultaţi setările pentru a obţine plug-in-uri!\n +* publicat plug-in QR (scanează parole, afişează parole ca un cod QR, transferă înregistrările la alte dispozitive cu KP2A)\n +* publicat plugin-ul InputStick (transferă date de login la PC prin bluetooth - necesită stick USB InputStick)\n +* Aplicaţiile terţe pot acum pur şi simplu pune în aplicare interogarea KP2A pentru date de conectare. Eşti un dezvoltator? Te rog să adaugi asta la aplicația ta dacă îți este necesar!\n +* adăugat suport TOTP (compatibil cu KeeOTP şi TrayTotp)\n +* aplicația nu mai trebuie să fie oprită de Android atunci când baza de date este deschisă\n +* baza de date nu mai este blocat atunci când se părăsește aplicația cu butonul înapoi (a se vedea setările)\n +* afişează numele grupului în rezultatele căutării (*)\n +* meniu adăugat în rezultatele căutării incluzând opțiunea \"Navighează la părinte\"(*)\n +* adăugat opţiunea de a afişa numele grupului la înregistrare(*)\n +* (*) mulțumită lui Matthieu pentru implementarea acestor caracteristici!\n +* suport KeeChallenge (cu Yubikey NEO). Mulțumită lui Ben Rush pentru implementarea conectorului!\n +* îmbunătăţit interfața utilizatorului\n +* rezolvat un bug în interfața Google Drive\n +* adăugat posibilitatea de a dezactiva opțiunea \"donează\"\n +* icoana de la QuickUnlock este acum ascunsă implicit pe dispozitive cu Android 4.2+\n + +Versiunea 0.9.3 r5\n +* fixări încorporate de la Xamarin: Keepass2Android este acum compatibil cu ART pe Android 4.4.2. În sfârșit!\n +* Rezolvat bug-uri: bug-uri în sincronizare (reîmprospătează display-ul, verificări corecte pentru modificările la http), bug-uri pe dispozitive Android 2.x, bug-uri în implementări de stocare Google Drive şi OneDrive, golește clipboard la închiderea bazei de date, bug cu deschiderea ataşamentelor, probleme cu afișarea tastaturii\n + +Versiunea 0.9.3\n +* Tastatură nouă cu multe îmbunătățiri. Vedeți setările pentru a o personaliza.\n +* suport read-only pentru kdb (fișiere Keepass 1). Experimental!\n +* adăugat suport SFTP\n +* adăugată soluție pentru bug-ul în ART (Android 4.4.2)\n +* Bug-uri rezolvate\n + +Versiunea 0.9.2\n +* Adăugat suport OTP (compatibil cu plugin-ul OtpKeyProv)\n +* Integrat suport NFC pentru OTP-uri din YubiKey NEO \n +* Câteva îmbunătățiri interfață\n +* Integrat librărie Keepass 2.24\n +* Adăugat opţiunea de a opri procesul aplicației (a se vedea setările)\n +* Îmbunătăţit validarea certificatelor SSL\n +* Bug-uri rezolvate\n + +Versiunea 0.9.1\n +* Suport pentru SkyDrive (doar pentru ediția obișnuită Keepass2Android)\n +* probleme cu integrarea Google Drive rezolvate\n +* adăugat suport NTLM Versiunea 0.9\n * Suport integrat pentru Dropbox şi Google Drive (citire/scriere baze de date; doar ediţia normală Keepass2Android)\n * Browser fişiere integrat (bazat pe android-filechooser de HBA)\n -* Interfaţă îmbunătăţită pentru creearea de noi baze de date\n +* Interfaţă îmbunătăţită pentru crearea de noi baze de date\n * Include font personalizat DejaVu Sans Mono pentru afişarea parolelor\n -* Bug fixes +* Bug-uri rezolvate Versiunea 0.8.6\n * Suport pentru cifrul Twofish\n * Permite editarea de grupuri\n * Permite mutarea de intrări şi grupuri\n * Icoana QuickUnlock poate fi făcută transparentă (setări)\n -* Bug fixes - Versiunea 0.8.5\n +* Bug-uri rezolvate + +Versiunea 0.8.5\n * Fişierele remote sunt stocate local în cache-ul aplicaţiei pentru a permite utilizare offline (inclusiv editare şi sincronizare ulterioară). Verificaţi setările.\n * Icoană de notificare pentru a vizualiza starea de blocare a bazei de date (verificaţi setările)\n -* Determinare imbunătăţită a stării de blocare în unele situaţii\n -* Bazele de date sunt incărcate în memorie în timpul introducerii parolei pentru scurtarea timpului de incărcare (verificaţi setările)\n -* Se pot adăuga intrări în grupul rădăcină\n -* Bug fixes (rezolvă câmpurile referinţă, probleme cu tastatura pe aparatele italiene şi chineze) - Versiunea 0.8.4\n -* Modificările externe ale bazei de date sunt detectate şi combinate la salvare\n +* Determinare îmbunătăţită a stării de blocare în unele situaţii\n +* Bazele de date sunt încărcate în memorie în timpul introducerii parolei pentru scurtarea timpului de încărcare (verificaţi setările)\n +* Se pot adăuga înregistrări în grupul rădăcină\n +* Bug-uri rezolvate (se rezolvă câmpurile referinţă, probleme cu tastatura pe aparatele italiene şi chineze) + +Versiunea 0.8.4\n +* Modificările externe ale bazei de date sunt detectate şi îmbinate la salvare\n * S-a îmbunătăţit performanţa la încărcare\n * Bară de căutare îmbunătăţită cu sugestii\n * Logo nou pentru aplicaţie!\n @@ -346,14 +566,14 @@ Mulţumiri lui Alex Vallat pentru contribuţiile sale la cod!\n Mulţumiri lui Niki Hüttner (www.close-cut.de) pentru noul logo!\n Versiunea 0.8.3\n -* index utilizator/TAN afişat în lista de înregistrări (vezi setări)\n +* Index utilizator/TAN afişat în lista de înregistrări (vezi setări)\n * Înregistrările pot fi create dacă o căutare din browser nu găseşte rezultate\n * Tastatura KP2A oferă posibilitatea de a căuta date de logare pentru aplicaţia curentă\n * Aplicaţia se închide automat după selectarea unei înregistrări de folosit cu tastatura\n * Dialogul de selecţie a tastaturii se deschide automat după căutarea după URL (vezi setări)\n * Substituenţii din câmpuri sunt înlocuiţi înainte de copiere (majoritatea sunt suportaţi)\n -* fixuri pentru bug-uri minore -   +* Bug-uri minore rezolvate + Versiunea 0.8.2\n * suport pentru autentificare Digest în WebDAV\n * bugfix-uri (OI File manager, Deschide URL) @@ -363,48 +583,72 @@ Mulţumiri lui Niki Hüttner (www.close-cut.de) pentru noul logo!\n * Noi traduceri adăugate (mulţumiri contribuitorilor!) Versiunea 0.8\n -* îmbunătăţiri pentru interfaţa cu utilizatorul mai ales pentru Android 4.x\n -* permite folosirea unor managere de fişiere în mod deliberat pentru selectarea fişierelor\n -* adăugat un mod mai sigur pentru deschiderea de ataşamente (folosind un director cache)\n +* Îmbunătăţiri pentru interfaţa cu utilizatorul mai ales pentru Android 4.x\n +* Permite folosirea unor managere de fişiere în mod deliberat pentru selectarea fişierelor\n +* S-a adăugat un mod mai sigur pentru deschiderea de ataşamente (folosind un director cache)\n * Reparat erori la Editare activitate\n * probabil s-au introdus bug-uri noi :-) Posibilitate extinsă de a dona o bere sau altceva Versiunea 0,7\n * a crescut viteza de încărcare: transformarea cheii este acum de 10x mai rapidă!\n -* adăugat tastatura Keepass2Android: comută la aceasta tastatura pentru a introduce detaliile. Vă protejează de programe ce scanează clipboardul după parole (dezactivează vechile notificări clipboard din opţiuni)\n +* adăugat tastatura Keepass2Android: comută la aceasta tastatura pentru a introduce detaliile. Vă protejează de programe ce scanează clipboard-ul după parole (dezactivează vechile notificări clipboard din opţiuni)\n * Adăugat opţiunea de a dona o bere sau altceva (vezi meniul) Versiunea 0.6.2\n -* integrare Google Drive/Dropbox /...: utilizaţi aplicaţiile oficiale Google Drive sau Dropbox şi deschide orice fişier .kdbx. Acest lucru va deschide acum KP2A.\n -* Dialog căutare îmbunătăţit \n +* Integrare Google Drive/Dropbox /...: utilizaţi aplicaţiile oficiale Google Drive sau Dropbox şi deschide orice fişier .kdbx. Acest lucru va deschide acum KP2A.\n +* Dialog de căutare îmbunătăţit \n * Îmbunătăţit rezultate căutare pentru URL-uri împreună cu subdomenii\n -* adăugat în meniu opţiuni pentru a da feedback, şi evalua sau traduce aplicaţia\n +* adăugat în meniu opţiuni pentru a da feedback, evalua sau traduce aplicaţia\n \n -versiunea 0.6.1\n -* detectează dacă baza de date se modifică în fundal (i.e. datorită unei aplicaţii de sincronizare)\n +Versiunea 0.6.1\n +* Detectează dacă baza de date se modifică în fundal (i.e. datorită unei aplicaţii de sincronizare)\n * S-a îmbunătăţit căutarea din URL-uri din navigator\n -* dialog de confirmare când se renunţă la modificări\n +* Dialog de confirmare când se renunţă la modificări\n \n -versiunea 0.6\n -Versiunea publică iniţială +Versiunea 0.6\n +Versiunea publică iniţială + 30 de secunde 1 minut 5 minute - 10 minutes - 15 minutes - 30 minutes - 1 hour - Never + 10 minute + 15 minute + 30 de minute + o oră + Niciodată + + + Bază de date Keepass 2 (.kdbx) + KeePass 2 XML (necriptat) (.xml) + KeePass CSV (necriptat) (.csv) Mic Mediu Mare + + Holo Light + Holo Dark + + Design Nu reține numele utilizator și parola - Reține numele de utilizator + Reține doar numele de utilizator Reține numele de utilizator și parola + + Doar parolă + Parolă + fișier cheie + Parolă + OTP + Parolă + OTP secret (modul de recuperare) + Parolă + Challenge-Response + Parolă + Challenge-Response secret (modul de recuperare) + + + Ignoră eșecuri de validare a certificatului + Avertizează când validarea eșuează + Nu accepta certificate invalide + diff --git a/src/keepass2android/Resources/values-ru/strings.xml b/src/keepass2android/Resources/values-ru/strings.xml index 00baeb15..1be32d23 100644 --- a/src/keepass2android/Resources/values-ru/strings.xml +++ b/src/keepass2android/Resources/values-ru/strings.xml @@ -65,6 +65,7 @@ Цифры 0…9 Keepass2Android поставляется БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ. Это свободное ПО и Вы можете распространять его по лицензии GPL v2 или более поздней. \u2026 + Скопировать в буфер Введите имя файла базы данных Доступ Отмена diff --git a/src/keepass2android/Resources/values-sk/strings.xml b/src/keepass2android/Resources/values-sk/strings.xml index 16ad3ee2..274be51f 100644 --- a/src/keepass2android/Resources/values-sk/strings.xml +++ b/src/keepass2android/Resources/values-sk/strings.xml @@ -65,6 +65,7 @@ Číslice Keepass2Android je poskytovaný BEZ AKEJKOĽVEK ZÁRUKY; Toto je voľne dostupný softvér a môžete ho redistribuovať za podmienok licencie GPL verzie 2 alebo novšej. \u2026 + Kopírovať do schránky Vložte názov databázy Prístup Zrušiť diff --git a/src/keepass2android/Resources/values-sl/strings.xml b/src/keepass2android/Resources/values-sl/strings.xml index 7ad103b9..d2604ae3 100644 --- a/src/keepass2android/Resources/values-sl/strings.xml +++ b/src/keepass2android/Resources/values-sl/strings.xml @@ -1,4 +1,662 @@ - + + Odziv + Domača stran + Keepass2Android je upravitelj gesel, ki omogoča branje/pisanje podatkovnih zbirk KeePass 2.x na Androidu. + Uporabniški vmesnik temelji na predelavi KeepassDroida, ki ga je razvil Brian Pellin. Koda za opravila podatkovnih zbirk temelji na KeePassu od Dominika Reickla. Robot Android je kopirano ali prirejeno delo izdelka, ki ga ustvarja in deli Google in je uporabljeno v skladu s pogoji opisanimi v licenci za priznanje avtorstva Creative Commons 3.0. + Podpora SFTP je vgrajena z uporabo knjižnice JSch pod licenco BSD, ki jo je ustvaril JCraft, Inc. + Sprejmi + Zavrni + Dodaj vnos + Ustvari vnos za URL + Dodaj skupino + Dodaj skupino + Uredi skupino + Algoritem + Algoritem + Keepass2Android + KP2A + Keepass2Android Offline + KP2A Offline + Časovna omejitev programa + Čas pred zaklenitvijo podatkovne zbirke, ko je program nedejaven. + Uniči opravilo programa + Gumb Zapri + Prikaži gumb za uničenje opravila programa na zaslonu gesla (za uporabnike paranoida) + Program + Nastavitve programa + Prikaži ime skupine v rezultatih iskanja + Prikaži ime skupine pod nazivi vnosov v rezultatih iskanja. Uporabno, če ima več vnosov enako ime. + Skupina za prikaz je sedaj: %1$s + Prikaži ime skupine v pogledu vnosov + Žal Keepass2Android ne more obdelati vrnjenega URI-ja %1$s. Navežite stik z razvijalcem! + Varnost + Prikaz + Dostop z vnosom gesla + Hitro odklepanje + Ravnanje z datotekami + Tipkovnica + Izvozi podatkovno zbirko … + Uvozi podatkovno zbirko v notranjo mapo + Uvozi datoteko ključa v notranjo mapo + Preklapljanje tipkovnice + Na voljo samo v krajevnih datotekah. + Datoteka je shranjena v notranji mapi. + Datoteka podatkovne zbirke kopirana v notranjo mapo. Pritisnite V redu, da odprete iz novega mesta. Opomba: ne pozabite redno izvoziti podatkovno zbirko na varno pomnilniško napravo! + Datoteka ključa je bila kopirana v notranjo mapo. Prepričajte se, da imate varno varnostno kopijo, preden izbrišete iz trenutnega mesta! + Notranje mape ni mogoče uporabiti, ko si program ne zapomni mesta datoteke ključa. Spremenite varnostne nastavitve. + Oklepaji + Prekliči + Odložišče počiščeno. + Časovna omejitev odložišča + Čas pred čiščenjem odložišča po kopiranju uporabniškega imena ali gesla + Izberite, da kopirate uporabniško ime na odložišče + Izberite, da kopirate geslo na odložišče + Vnos je na voljo preko tipkovnice K2PA + je na voljo + Pogovornega okna za izbiranje metode vnosa ni bilo mogoče odpreti. Ročno omogočite tipkovnico. + Omogočite tipkovnico Keepass2Android v svojih sistemskih nastavitvah. + Ustvarjanje ključa podatkovne zbirke … + Trenutna skupina + Trenutna skupina: Skrbniki + Podatkovna zbirka + Številke + Keepass2Android je brez VSAKRŠNE GARANCIJE; to je brezplačna programska oprema in lahko jo razširjate pod pogoji GPL-a različice 2 ali kasnejše. + \u2026 + Kopiraj na odložišče + Vnesite ime datoteke podatkovne zbirke + Dostopano + Prekliči + Pripombe + Oznake + Preglasi URL + Potrdite geslo + Ustvarjeno + Poteče + Ime skupine + Datoteka ključa (izbirno) + Datoteka ključa + Spremenjeno + Geslo + Shrani + Ime + URL + Uporabniško ime + Dodatna polja nizov + Datotečne priponke + Keepass2Android ne more obdelati tega url-ja. + Napaka pri ustvarjanju skupine. + Nadrejene mape ni bilo mogoče ustvariti. + Ta datoteka že obstaja. + Določanje nastavitev podatkovne zbirke je spodletelo. + Zagon povezave je spodletel. + Zahtevano je ime datoteke. + Ustvarjanje datoteke ni bilo mogoče + Neveljavna podatkovna zbirka. + Neveljavna pot. + Zahtevano je ime. + Zahtevano je geslo ali datoteka ključa. + Vsaj eno vrsto ustvarjanja gesla je treba izbrati + Gesli se ne ujemata. + Ponovitve morajo biti številka. + Zahtevan je naziv. + Vnesite pozitivno številko v polju dolžine + Datoteke ni bilo mogoče najti. + Brskalnik datotek + Ustvari geslo + Skupina + pripomba + potrdi geslo + ustvarjeno geslo + Ime skupine + datoteka ključa + dolžina + geslo + Geslo + ime + url + preglasi url + oznaka 1, oznaka 2 + uporabniško ime + Neveljavno geslo ali datoteka ključa. + Neveljaven algoritem. + Oblike podatkovne zbirke ni mogoče prepoznati. + Datoteka ključa ne obstaja. + Nobena datoteka ključa ni izbrana. + Datoteka ključa je prazna. + Dolžina + Velikost seznama skupin + Velikost besedila na seznamu skupin + Nakladanje podatkovne zbirke … + Male črke + ***** + Zakrij geslo + Privzeto skrij gesla + O programu + Spremeni glavni ključ + Kopiraj geslo + Kopiraj uporabnika + Ustavri + Nastavitve + Nastavitve podatkovne zbirke + Izbriši + Premakni v drugo skupino + Premakni + Pomakni se v nadrejeno skupino + Darujte pivo … + Uredi + Skrij geslo + Zakleni podatkovno zbirko + Odpri + Preimenuj + Išči + Napredno iskanje + Pojdi na URL + Spremeni podatkovno zbirko … + Minus + Nikoli + Da + Ne + Ni vnosov v podatkovni zbirki ali skupini. + Ni rezultatov iskanja + Ni ročnika za ta url. + Odpri nedavno podatkovno zbirko (kliknite za odpiranje) + Ne išči po vnosih varnostne kopije in Koša + Izpusti skupini \'Varnostna kopija\' in Koš iz rezultatov iskanja + Ime datoteke podatkovne zbirke KeePass + Vnesite geslo podatkovne zbirke + Izberite vrsto glavnega ključa: + Ustvarjanje nove podatkovne zbirke … + Ustvari podatkovno zbirko + V teku … + Si zapomni mesto datotek ključa + Shrani datoteko ključa + Odstrani + Rijndael (AES) + Korenska mapa + Ponovitve šifriranja + Večje št. ponovitev šifriranja zagotovi dodatno zaščito pred vdori z grobo silo, vendar lahko zelo upočasnijo nalaganje in shranjevanje. + ponovitve + Ime podatkovne zbirke + Privzeto uporabniško ime za nove vnose + Shranjevanje podatkovne zbirke … + Izvažanje podatkovne zbirke … + Podatkovna zbirka uspešno izvožena! + Prostor + Išči + Prikaži geslo + Razvrsti po … + Razvrsti po imenu + Razvrsti po datumu nastanka + Razvrsti po datumu spremembe + Ohrani privzeti vrtni red + Poseben + Najdite, kar + Rezultati iskanja + Išči v + Izberite drug vnos + Odprite želeno skupino in potem pritisnite \"%1$s\"! + Vstavi tu + Twofish + Podčrtaj + Nepodprta različica podatkovne zbirke + Velike črke + Vaša kartica SD je trenutno v načinu samo za branje. Shranjevanje sprememb podatkovne zbirke morda ni mogoče. + Vaša kartica SD trenutno ni priklopljena na vaši napravi. Podatkovne zbirke morda ne bo mogoče naložiti ali ustvariti. + Različica + Zgodovina različic + Keepass2Android razvija Philipp Crocoll. + Hvala %1$s za prispevke kode. + Hvala %1$s za prispevke pri oblikovanju ikon in razporeditve. + Vtičnik Twofish Cipher za KeePass je razvil Scott Greenberg in je vključen v KP2A. + Izbirnik datotek za Android je razvil Hai Bison + Tipkovnica KP2A temelji na tipkovnici Gingerbread odprtokodnega projekta Android in uporablja kodo Upravitelja vtičnikov Tipkovnice za hekerje Klausa Weidnerja. + Upoštevajte + Prispevali so + Običajni izraz + TAN ob uporabi poteče + Ob uporabi označi vnose TAN kot potekle + Prikaži uporabniško ime na seznamu + Prikaži uporniška imena pod nazivi vnosov. Uporabno za več računov ali TAN-e. + Zapomni si podatkovne zbirke + Zapomni si nedavno odprte podatkovne zbirke in jih prikaži na zaslonu Odpri podatkovno zbirko. + Keepass2Android: Najdi geslo + Izključi potekle vnose + Možnosti + Razlikovanje velikosti črk + Odpri datoteko … + Ustvari novo podatkovno zbirko … + Odpri URL … + Uvozi datoteko v novo podatkovno zbirko … + Določen mora biti celoten URL, vključno s protokolom, kot je http://. + Datoteka za uvoz bo zbrana v naslednjem koraku. + Omogoči Hitro odklepanje + Vnesite zadnje %1$d znake svojega gesla. + Hitro odklepanje! + Zapri podatkovno zbirko + Privzeto omogoči Hitro odklepanje + Določi, ali je Hitro odklepanje privzeto omogočeno. + Zaščiti prikaz podatkovne zbirke + Če je omogočeno, zaslonske slike niso dovoljene in na seznamu nedavnih programov ni prikazana sličica. + Skrij ikono Hitrega odklepanja + Hitro odklepanje na žalost ne deluje brez prikaza obvestilne ikone. Izberite to možnost, da uporabite prosojno ikono. + Skrij ikono Hitrega odklepanja + Hitro odklepanje za pravilno delovanje zahteva obvestilo. Izberite to možnost, da prikažete obvestila brez ikone. + Dolžina ključa Hitrega odklepanja + Največje število znakov, ki naj se uporabi v geslu Hitrega odklepanja. + Hitro odklepanje je spodletelo: nepravilno geslo! + Mapa datotečnih priponk + Mapa, kamor se shranjujejo datotečne priponke. + Shrani priponko + Izberite, kam naj se shranjujejo priponke. + Shrani na kartico SD + Shrani v predpomnilnik in odpri + Datoteka shranjena v %1$s. + Datoteke ni bilo mogoče shraniti v %1$s. + Zapomni si iskalno besedilo? + Ali bi radi shranili iskalno besedilo \"%1$s\" v izbranem vnosu, da ga naslednjič samodejno najdete? + Neveljavna oblika datuma/časa datuma poteka! + Za vsak niz je zahtevano ime polja. + Ime polja + Vrednost polja + Zaščiteno polje + Dodaj datotečno priponko … + Dodaj dodaten niz + Izbriši dodaten niz + %1$s: zaklenjena. Hitro odklepanje omogočeno. + %1$s: odklenjena. + Vnesite poverila strežnika + Prenosi datotek + Uporabi prenose datotek za zapisovanje podatkovnih zbirk + Zakleni, ko je zaslon izklopljen + Zakleni podatkovno zbirko, ko je zaslon izklopljen. + Počisti vneseno glavno geslo + Počisti vneseno glavno geslo ob zapuščanju zaslona brez odklepanja podatkovne zbirke. + Zakleni ob končanju programa + Zakleni podatkovno zbirko ob končanju programa s pritiskom na gumb Nazaj. + Skrij možnost za darovanje + Ta nastavitev je za darovalce. Na voljo je samo, ko uporabite Keepass2Android za nekaj časa. + Brez darovanj ta program ni bi obstajal in ne bi prejel neprestanih izboljšav! Če še niste darovali, razmislite o tem sedaj! + Predpomnenje podatkovne zbirke + Ohrani kopijo oddaljenih datotek podatkovnih zbirk v mapi predpomnilnika programa. To omogoča uporabo oddaljenih podatkovnih zbirk tudi v nepovezanem načinu. + Potrdila SSL + Določite vedenje, ko preverjanje veljavnosti potrdila spodleti. Opomba: na svojo napravo lahko namestite potrdila, če preverjanje veljavnosti spodleti! + Počisti predpomnilnik? + To bo izbrisalo vse predpomnjene datoteke podatkovnih zbirk. Vse spremembe, ki ste jih naredili v nepovezanem načinu in niso bile usklajene, bodo izgubljene! Nadaljuj? + Preveri za spremembe + Pred shranjevanjem sprememb preveri, ali je bila datoteka spremenjena od zunaj. + Preveri za podvojene UUID-je + Preveri, ali je datoteka podatkovne zbirke pokvarjena z večkratnimi vnosi z istim ID-jem. To lahko povzroči nepričakovano vedenje. + Obvestila odložišča + Naredi uporabniško ime in geslo dostopno preko vrstice za obvestila in odložišča. Pazite se vohljačev gesel! + Loči obvestila + Prikaži ločena obvestila za kopiranje uporabniškega imena in gesla na odložišče in omogočanje tipkovnice. + Obvestilo tipkovnice KP2A + Naredi poln vnos dostopen preko tipkovnice KP2A (priporočljivo). + Preklopi tipkovnico + Odpri pogovorno okno za izbiro tipkovnice, ko je vnos na voljo preko tipkovnice KP2A po iskanju iz brskalnika. + Samodejno preklopi na napravah s skrbniškim dostopom + Samodejno prekopi na tipkovnico KP2A, ko je vnos odprt. Zahteva skrbniški dostop in program Secure Settings z modulom System+. + Samodejno preklopi samo po iskanju + Samodejno preklopi samo na tipkovnico KP2A po uporabi zmožnosti Deli URL (vendar ne ob odpiranju vnosa na drug način) + Preklapljanje tipkovnice nazaj + Preklopi nazaj na prejšnjo tipkovnico, ko ni odprt noben vnos. + Ikona obvestila, ko je odklenjena + Prikaži ikono obvestila, ko je podatkovna zbirka odklenjena. + Prednaloži datoteko podatkovne zbirke + Začni z nalaganjem v ozadju ali prejemanjem datoteke podatkovne zbirke med vnosom gesla. + Ali želite prepisati obstoječo dvojiško datoteko z enakim imenom? + Prepiši obstoječi dvojiško datoteko? + Prepiši + Preimenuj + Dodajanje datotečne priponke je spodletelo. + Koš + Ali želite ta vnos trajno izbrisati? Pritisnite Ne, da ga premaknete v Koš. + Ali želite to skupino trajno izbrisati? Pritisnite Ne, da jo premaknete v Koš. + Trajno izbriši? + Ponovno naloži datoteko? + Trenutno odprto datoteko je drug program spremenil. Ali jo želite ponovno naložiti? + Ali res želite zavreči narejene spremembe? (Gumb Shrani je na vrhu obrazca.) + Zavrzi spremembe? + Predlagajte ali glasuje za izboljšave + Ocenite ta program + Prevedite KP2A + Dodajanje vnosa … + Dodajanje skupine … + Brisanje vnosa … + Brisanje skupine … + Nastavljanje gesla … + Razveljavljanje sprememb … + Preoblikovanje glavnega ključa … + Odkodiranje podatkovne zbirke … + Razčlenjevanje podatkovne zbirke … + Preverjanje ciljne datoteke za spremembe … + Združi spremembe + Datoteka podatkovne zbirke je bila spremenjena od zunaj. Ali želite pred shranjevanjem naložiti in združiti spremembe? Izberite Ne, če želite prepisati zunanje spremembe. + Združevanje sprememb … + Da, združi + Ne, prepiši + Usklajevanje predpomnjene podatkovne zbirke … + Prejemanje oddaljene datoteke … + Pošiljanje datoteke … + Obnavljanje oddaljene datoteke … + Datoteke so usklajene. + Podatkovna zbirka uspešno usklajena! + Preverjanje podatkovne zbirke za spremembe … + Shranjevanje na oddaljeno %1$s ni bilo mogoče. Ponovno shranite ali uporabite meni Uskladi, ko je oddaljena povezava spet na voljo. + Odpiranje iz oddaljene %1$s ni mogoče. Naložena je bila datoteka iz krajevnega predpomnilnika. V podatkovni zbirki lahko še vedno naredite spremembe in jih uskladite kasneje. + Oddaljena datoteka posodobljena. + Odprta je bila krajevna datoteka zaradi spora s spremembami v oddaljeni datoteki. Uporabite meni Uskladi, da jih združite. + Oddaljena datoteka in predpomnilnik sta usklajena. + Krajevna predpomnjena kopija %1$s posodobljena. + Ni zaznanih sprememb. + Posodobljena predpomnjena pomožna datoteka OTP: oddaljeni števec je bil višji. + Posodobljena predpomnjena pomožna datoteka OTP: krajevni števec je bil višji. + Usklajevanje pomožne datoteke OTP … + datoteka podatkovne zbirke + pomožna datoteka OTP + Pojavila se je napaka: + Podatkovna zbirka je pokvarjena: najdeni podvojeni ID-ji. (Ali ste shranili z Minikeepassom?) Ponovno uvozite v novo podatkovno zbirko s KeePassom 2 za PC in izberite \'Ustvari nove ID-je\'. + To sporočilo o napaki lahko onemogočite v Nastavitve/Nastavitve programa/Ravnanje z datotekami/Preveri za podvojene UUID-je. Upoštevajte, da lahko naletite na nepričakovano vedenje. Priporočljivo je popraviti podatkovno zbirko. + Uskladi podatkovno zbirko … + Skupine ni mogoče premakniti v to skupino. + Danes je Oktoberfest! Če vam je Keepass2Android všeč: ali ne bi bil današnji dan pravi dan, da mi kupite pivo? + 10. maj? To je moj rojstni dan! Če vam je ta program všeč, zakaj mi ne pošljete voščilnice za rojstni dan skupaj z majhnim darilom? To bi me zelo osrečilo! :-) + Zamudili ste moj rojstni dan 10. maja! Če vam je ta program všeč, zakaj mi ne pošljete voščilnico za rojstni dan skupaj z majhnim darilom? Ni še prepozno, da me osrečite! :-) + Povejte mi več! + Ne, ni mi toliko všeč + gostitelj (npr.: 192.168.0.1) + vrata + Začetna mapa (izbirno): + Vnesite podatke za prijavo SFTP: + Izberite vrsto pomnilniške naprave: + Krajevna datoteka + Dobi iz programa tretje osebe + Pošlji v program tretje osebe + FTP + HTTP (WebDav) + HTTPS (WebDav) + Dropbox + Dropbox (mapa KP2A) + Če dostopa KP2A ne želite dati celemu Dropboxu, lahko izberete to možnost. Zahtevala bo samo dostop do mape Apps/Keepass2Android. To je posebej primerno ob ustvarjanju nove podatkovne zbirke. Če jo že imate, kliknite na to možnost, da ustvarite mapo, v njo vstavite svojo datoteko (iz računalnika) in ponovno izberete to možnost, da datoteko odprete. + Google Drive + OneDrive + SFTP (prenos datotek SSH) + Začenjanje dostopa do datoteke + Mesto podatkovne zbirke + Svojo podatkovno zbirko lahko krajevno shranite na svoji napravi Android ali v oblak (samo povezana različica). Keepass2Android da podatkovno zbirko na razpolago tudi, če niste povezani. Ker je podatkovna zbirka varno šifrirana s 256-bitnim šifriranjem AES, ne bo nihče mogel dostopati do vaših gesel razen vas. Priporočamo Dropbox: na voljo je na vseh vaših napravah in ponuja tudi varnostne kopije prejšnjih različic. + Izberite mesto za shranjevanje podatkovne zbirke: + Spremeni mesto + Glavno geslo + Vaša podatkovna zbirka je šifrirana z geslom, ki ga vnesete tu. izberite močno geslo, da zagotovite varnost svoje podatkovne zbirke! Nasvet: sestavite stavek ali dva in za geslo uporabite prve črke besed. Vključite ločila. + Izberite glavno geslo, da zaščitite sojo podatkovno zbirko: + Datoteka ključa + Datoteka ključa je v bistvu geslo shranjeno v datoteki. Datoteke ključa so značilno močnejše od glavnih gesel, ker so lahko veliko bolj zapletene; vendar jih je težje ohraniti skrivne. če svojo podatkovno zbirko shranite v oblak, tam ne shranite tudi datoteko ključa! To bi jo naredilo popolnoma neuporabno! Pomembno: ne spremenite vsebine datoteke ključa po ustvarjanju podatkovne zbirke! + Izberite, ali želite poleg glavnega gesla uporabiti datoteko ključa: + Uporabi datoteko ključa + Napaka pri dodajanju datoteke ključa! + Naloži pomožno datoteko OTP … + Vnesite naslednja gesla za enkratno uporabo (OTP-je). Potegnite svoj ključ Yubikey NEO na zadnji strani svoje naprave, da vnesete preko NFC-ja. + OTP %1$d + Programa, ki lahko opravi preizkus, ni bilo mogoče najti. Namestite Yubichallenge iz trgovine Google Play. + Pomožne datoteke OTP ni mogoče naložiti! + Uporabite vtičnik OtpKeyProv v KeePassu 2.x (PC), da nastavite svojo podatkovno zbirko za uporabo z OTP-ji! + Najprej izberite podatkovno zbirko. OTP je zavržen zaradi varnostnih razlogov. + OTP zavržen: vsi OTP-ji že vneseni! + Najprej zaprite podatkovno zbirko. OTP je zavržen. + (En ali več OTP-jev je že na voljo) + Skrivnost OTP (npr. 01 23 ab cd …) + Napaka pri razčlenjevanju skrivnosti OTP! + Ustvarjanje ključa OTP je spodletelo! Prepričajte se, da ste vnesli pravilne OTP-je. + Napaka pri posodabljanju pomožne datoteke OTP! + Shranjevanje pomožne datoteke OTP … + Odgovor izziva je nepravilen. + Nalaganje pomožne datoteke izziva ni bilo mogoče! + Uporabite vtičnik KeeChallenge v KeePassu 2.x (PC), da nastavite svojo podatkovno zbirko za uporabo z odgovorom izziva! + Napaka pri posodabljanju pomožne datoteke OTP! + Ime polja semena TOTP + Če uporabljate vtičnik KeePassa 2 \"TrayTotp\" s samo privzetimi nastavitvami, tu vnesite ime polja semena glede na nastavitve na računalniku. + Ime polja nastavitev TOTP + Tu vnesite ime polja nastavitev za TraxyTotp. + TrayTotp + Nalaganje … + Vtičniki + Ime paketa: + Opis (ni preverjen): + Avtor (ni preverjen): + omogočen + onemogočen + Najdi vtičnike na spletu + Področja + %1$s zahteva poverila za %2$s. + %1$s zahteva poverila. Izberite vnos. + Omogočen + Obvestila dejanj podatkovne zbirke + Vtičnik bo obveščen, ko je podatkovna zbirka odprta, zaprta ali shranjena. + Trenutni podatki vnosa + Vtičnik bo prejel vse podatke o trenutnem vnosu podatkovne zbirke in mu bo omogočeno ponujanje dejanj in spreminjanje svojega prikaza. + Poizvedi po svojih poverilih + Vtičniku bo dovoljena poizvedba za poverila, ki so povezana s njegovim lastnim programskim paketom. + Poizvedi za poverila + Vtičniku bo dovoljena poizvedba za poverila za namerne spletne strani ali programe. + Dobi več vrst pomnilniških naprav + Opozorilo: preverjanje veljavnosti potrdila strežnika je spodletelo: %1$s. Namestite ustrezno korensko potrdilo na svoji napravi ali glejte nastavitve! + Napaka: preverjanje veljavnosti potrdila strežnika je spodletelo: Namestite ustrezno korensko potrdilo na svoji napravi ali glejte nastavitve! + Izberite obliko datoteke + Žal je OS Android uničil Keepass2Android. Zaradi varnostnih razlogov Keepass2Android ni shranil vaših poveril na disk, tako da morate podatkovno zbirko ponovno odpreti. Opomba: to se redkokdaj zgodi. Če se, mi to sporočite na crocoapps@gmail.com. + Datoteka je samo začasno na voljo za Keepass2Android. + Izbrana datoteka je samo za branje. + Izbrana datoteka za Keepass2Android je samo za branje zaradi omejitev na Androidu 4.4+. + Da jo uporabite, jo morate kopirati na drugo mesto. + Daj jo uredite, jo morate kopirati na drugo mesto. + Kliknite V redu, da izberete mesto, kamor je treba kopirati datoteko. + Prekliči, odpri samo za branje. + Kopiranje datoteke … + Upoštevajte: naložili ste podatkovno zbirko Keepass 1. Keepass2Android je nedavno dodal podporo za pisanje za to obliko podatkovne zbirke. Čeprav je prestala temeljiti preizkus avtor ne poda nobene garancije, da bodo podatki pravilno shranjeni. Vedno shranite varnostno kopijo izvirne podatkovne zbirke (Dropbox samodejno shrani nedavne različice), preden naredite spremembe. Prijavite katerokoli težavo. Hvala! + Dnevnik sprememb + Upoštevajte! To je predogledna različica in lahko vsebuje nekaj napak! Če izkusite *karkoli* nepričakovanega, me o tem obvestite (na Codeplexu ali po e-pošti). + + Različica 0.9.7\n + *podpora za pisanje za podatkovne zbirke Keepass 1 (kdb) (beta!)\n + * boljše nazaj na prejšnjo tipkovnico (deluje tudi na napravah brez skrbniškega dostopa)\n + * podpora za KeeChallenge z izzivi spremenljive dolžine\n + * preprečitev zajema zaslonskih slik iz zaslonov Hitrega odklepanja in gesel\n + * obratni vrstni red razvrščanja za razvrščanje po datumu spremembe (sedaj padajoče)\n + * popravki hroščev: pogled opomb se sedaj pravilno posodobi po spremembah, pogledi gesel sedaj pravilno skrijejo gesla na vseh napravah, popravljena težava, ki je dovoljevala dvakratno dodajanja vnosa, popravljena težava s prikazovanjem opozorila Podvojeni UUID-ji tudi po popravljanju podatkovne zbirke\n + + Različica 0.9.6\n + * omogoči uvažanje datoteke ključa in/ali krajevne podatkovne zbirke v notranjo mapo programa (glejte nastavitve)\n + *omogoči različne možnosti razvrščanja\n + * izboljšane nastavitve za samodejno preklapljanje tipkovnice\n + * posodobljena logotip programa in oblika obvestil, oblikoval Stefano Pignataro (http://www.spstudio.at)\n + * ustvarjalnik gesel si zapomni zadnje nastavitve\n + * nastavitev vidnosti obvestil zaslona za zaklepanje za Android 5\n + * sedaj se polja glavnega gesla počistijo, ko končate program brez klika V redu\n + * popravljena težava z manjkajočimi vnosnimi jeziki v nastavitvi tipkovnice na nekaterih napravah\n + * popravljena težava s samodejnim preklapljanjem tipkovnice na napravah s skrbniškim\n + * dodano preverjanje za pokvarjene podatkovne zbirke (podvojeni UUID-ji)\n + * samodejno ponovno naloži podatkovno zbirko, ko je sprememba, reši skrb za varnost glede razkritja glavnega gesla\n + * izboljšana razporeditev poljske majhne tipkovnice, popravljena tema nastavitev tipkovnice (zahvale Wiktorju Ławskiju)\n + + Različica 0.9.5\n + * Popravljene težave z brskanjem po datotekah (posebno na Androidu 4.4)\n + * Popravljena težava z nalaganjem datotek .kdb (Keepass 1) na Nexusu 5 z Androidom Lollipop\n + * Dodana možnost preprečitve zajemanja zaslonskih slik/prikazovanja programa na seznamu nedavnih programov\n + * Popravljena težava s shranjevanjem datotek na Google Drive (običajna izdaja)\n + * Omogoči datoteke ključa na namernih vrstah pomnilniških naprav (običajna izdaja)\n + * Posodobljen SDK Dropbox za vključitev uradnega varnostnega popravka (običajna izdaja)\n + * Posodobljena orodja za izgradnjo --> velikost apk povečana :-(\n +Obljubil sem več sprememb. Žal se bodo pojavila v naslednji izdaji. Te hitre popravke sem hotel objaviti v najkrajšem možnem času. + + + Različica 0.9.4\n + * dodana podpora za vtičnike: glejte nastavitve o tem, kako dobiti vtičnike!\n + * objavljen vtičnik QR (preišči gesla, prikaži gesla kot kodo QR, prenesi vnose na druge naprave KP2A)\n + * objavljen vtičnik InputStick (prenesi poverila na vaš PC preko Bluetootha - zahteva ključek USB InputStick)\n + * programi tretjih oseb lahko sedaj preprosto vgradijo poizvedbo KP2A za poverila. Ste razvijalec? Dodajte to v vaš program, če je primerno!\n + * dodana podpora za TOTP (združljivo z vtičnikoma KeeOTP in TrayTotp)\n + * Android naj ne bi več uničil programa, ko je podatkovna zbirka odprta\n + * podatkovna zbirka ni več zaklenjena, ko končate program z gumbom Nazaj (glejte nastavitve)\n + * prikaži imena skupin v pogledu rezultatov iskanja (*)\n + * dodan vsebinski meni v pogled rezultatov iskanja, vključno z možnostjo \"Premakni se v nadrejeno mapo\" (*)\n + * dodana možnost za prikaz imena skupine v pogledu vnosov (*)\n + * (*) Hvala Matthieu za teh lastnosti!\n + * podpora za KeeChallenge (z Yubikeyem NEO). Hvala Benu Rushu za vgradnjo priključka!\n + * izboljšan uporabniški vmesnik\n + * popravljen hrošč v vmesniku Google Drive\n + * dodana možnost za onemogočanje možnosti \"daruj\"\n + * ikona Hitrega odklepanja sedaj privzeto skrita na napravah z Androidom 4.2+\n vgradnjo + + Različica 0.9.3 r5\n + * Vgrajeni popravki od Xamarina: Keepass2Android je sedaj združljiv z ART-om na Androidu 4.4.2. Končno!\n + * Popravki hroščev: hrošči v usklajevanju (osvežitev zaslona, popravljeno preverjanje za spremembe na http-ju), hrošči na napravah z Androidom 2.x, hrošči v vgradnjah shranjevanja na Google Drive in OneDrive, čiščenje odložišča ob zapiranju podatkovne zbirke, hrošči ob odpiranju priponk, težave s prikazom tipkovnice\n + + + Različica 0.9.3\n + * Nova tipkovnica z veliko izboljšavami. Glejte nastavitve za prilagajanje.\n + * Podpora samo za branje za kdb (datoteke Keepass 1). Preizkusno!\n + * Dodana podpora za SFTP\n + * Dodano zaobidenje hrošča v ART-ju (Android 4.4.2)\n + * Popravki hroščev\n + + Različica 0.9.2\n + * Dodana podpora za OTP (združljivo z vtičnikom OtpKeyProv)\n + * Vgrajena podpora NFC za OTP-je iz YubiKeya NEO \n + * Več izboljšav UI-ja\n + * Vgrajena knjižnica Keepass 2.24\n + * Dodana možnost uničenja opravila programa (glejte nastavitve)\n + * Izboljšano preverjanje veljavnosti potrdil SSL\n + * Popravki hroščev\n + + + Različica 0.9.1\n + * Vgrajena podpora za SkyDrive (samo običajna izdaja programa Keepass2Android)\n + * popravljene težave z vgradnjo storitve Google Drive\n + * Dodana podpora za NTLM + + + + Različica 0.9\n + * Vgrajena podpora za Dropbox in Google Drive (podatkovne zbirke za branje/pisanje; samo redna izdaja programa Keepass2Android)\n + * Vgrajen brskalnik datotek po meri (osnovan na izbirniku datotek od HBA-ja)\n + * Izboljšan uporabniški vmesnik za ustvarjanje novih podatkovnih zbirk\n + * Vključena pisava po meri DejaVu Sans Mono za prikazovanje gesel\n + * Popravki hroščev + + + Različica 0.8.6\n + * Podpora za šifro Twofish\n + * Omogoča urejanje skupin\n + * omogoča premikanje vnosov in skupin\n + * Ikona Hitrega oklepanja je lahko prosojna (glejte nastavitve)\n + * Popravki hroščev + + + Različica 0.8.5\n + * Oddaljene datoteke so shranjene v krajevnem predpomnilniku programa, da omogočijo nepovezano uporabo (vključno z urejanjem in kasnejšim usklajevanjem). Glejte nastavitve. \n + * Ikona obvestila za predočenje stanje zaklepanja podatkovne zbirke (glejte nastavitve)\n + * Izboljšano določanje stanja zaklepanja v nekaterih razmerah\n + * Datoteke podatkovne zbirke se naložijo v pomnilnik, ko tipkate svoje geslo za povečanje hitrosti nalaganja (glejte nastavitve)\n + * Vnose lahko dodate v skrbniško skupino\n + * Popravki hroščev (razrešitev sklicnih polj, težav s tipkovnico na italijanskih in kitajskih napravah) + + + Različica 0.8.4\n + * Spremembe zunanjih podatkovnih zbirk se zaznajo in združijo ob shranjevanju\n + * Izboljšana zmogljivost nalaganja\n + * Izboljšana orodna vrstica za iskanje s predlogi\n + * Nov logotip programa!\n + * Dodana podpora za obliko .kdbp za hitrejše nalaganje/shranjevanje\n + * Izboljšana urejanje dodatnih nizov in skrit zaslon, ko je zaščiten\n +Hvala Alexu Vallatu za prispevke kode!\n +Hvala Nikiju Hüttnerju (www.close-cut.de) za nov logotip!\n + + Različica 0.8.3\n +* Kazalo uporabniških imen/TAN-ov prikazano na seznamu vnosov (glejte nastavitve)\n +* Vnose lahko ustvarite, če iskanje v brskalniku ne vrne rezultatov\n +* Tipkovnica KP2A ponuja možnost iskanja poveril za trenutni program\n +* Program se samodejno zapre po izbiri vnosa za uporabo na tipkovnici\n +* Pogovorno okno izbire tipkovnice se samodejno odpre po iskanju URL-ja (glejte nastavitve)\n +* Ograde v poljih vnosov se nadomestilo pred kopiranjem (podprta je večina ograd)\n +* Manjši popravki hroščev + + Različica 0.8.2\n +* Podpora za overitev Digest v protokolu WebDAV\n +* popravki hroščev (Upravitelj datotek OI, Odprt URL) + + Različica 0.8.1\n +* KP2A Offline in \"Povezana\" različica se lahko ponovno hkrati namestita\n +* Dodani novi prevodi (hvala vsem, ki ste prispevali!) + + Različica 0.8\n +* Izboljšan uporabniški vmesnik, posebno za naprave z Androidom 4.x\n +* Omogoči uporabo namernih upraviteljev datotek za izbiranje obstoječih datotek\n +* Dodan varnejši način za odpiranje priponk (preko mape predpomnilnika)\n +* popravljeni hrošči v dejavnosti urejanja\n +* verjetno uvedeni novi hrošči :-) + + Razširjena možnost darovanja piva ali kaj drugega + Različica 0.7\n +* Povečan čas nalaganja: ključne preobrazbe sedaj 10-krat hitrejše!\n +* Dodana zaslonska tipkovnica Keepass2Android: preklopite na to tipkovnico za vnos poveril. Ščiti vas pred vohljači gesel na odložišču (v možnostih onemogočite stara obvestila odložišča)\n +* Dodana možnost darovanja piva ali kaj drugega (glejte meni) + Različica 0.6.2\n +* Vgradnja storitve Google Drive/Dropbox/ ...: uporabite uradno storitev Google Drive ali program Dropbox in odprite katerokoli datoteko .kdbx. To bo sedaj prikazalo KP2A.\n +* Izboljšano pogovorno okno za iskanje\n +* Izboljšani rezultati iskanja za Deli URL s poddomenami\n +* Dodane možnosti za odziv, oceno in prevod programa v meniju\n +\n +Različica 0.6.1\n +* Zaznavanje sprememb podatkovnih zbirk v ozadju (zaradi nedejavnosti programa za usklajevanje)\n +* Izboljšano iskanje URL-jev iz brskalnika\n +* Pogovorno okno za potrditev ob opustitvi sprememb\n +\n +Različica 0.6\n +Začetna javna izdaja + + + 30 sekund + 1 minuta + 5 minut + 10 minut + 15 minut + 30 minut + 1 ura + Nikoli + + + Podatkovna zbirka KeePass 2 (.kdbx) + Keepass 2 XML (nešifriran) (.xml) + Keepass CSV (negšifriran) (.csv) + + + Majhna + Srednja + Velika + + + Holo svetla + Holo temna + + Oblika + + Ne zapomni si uporabniškega imena in gesla + Zapomni si samo uporabniško ime + Zapomni si uporabniško ime in geslo + + + Samo geslo + Geslo in datoteko ključa + Geslo in OTP + Geslo in skrivnost OTP (način obnovitve) + Geslo in odgovor izziva + Geslo in skrivnost odgovora izziva (način obnovitve) + + + Prezri spodletela preverjanja veljavnosti potrdil + Opozori, ko preverjanje veljavnosti spodleti + Ne sprejmi neveljavnih potrdil + + diff --git a/src/keepass2android/Resources/values-uk/strings.xml b/src/keepass2android/Resources/values-uk/strings.xml index 4f129bac..56489217 100644 --- a/src/keepass2android/Resources/values-uk/strings.xml +++ b/src/keepass2android/Resources/values-uk/strings.xml @@ -418,6 +418,8 @@ Помилка: не вдалося перевірити сертифікат сервера! Встановіть відповідний кореневий сертифікат на ваш пристрій або перегляньте налаштування! Виберіть формат файлу Вибачте! Keepass2Android був убитий ОС Android! З міркувань безпеки Keepass2Android не зберігає вибрані облікові дані на диску, тому потрібно повторно відкрити базу даних. Примітка: Це має відбуватися дуже рідко. Якщо це так, будь ласка, напишіть мені повідомлення на crocoapps@gmail.com. + Натисніть OK, щоб обрати місце, куди слід скопіювати файл. + Копіювання файлу... Журнал змін Будь ласка, зверніть увагу! Це попередній реліз і може мати деякі недоліки! Якщо у вас виникли *будь-які* несподіванки, будь ласка, дайте мені знати (на Codeplex або електронною поштою). diff --git a/src/keepass2android/Resources/values/strings.xml b/src/keepass2android/Resources/values/strings.xml index 29042820..a5e83cb2 100644 --- a/src/keepass2android/Resources/values/strings.xml +++ b/src/keepass2android/Resources/values/strings.xml @@ -538,6 +538,10 @@ Continue The URI you have entered does not look like a filename. Are you sure this is a valid file? + + Version 0.9.8b\n + * Bug fixes (Saving failed for some databases, exporting to local device not working, selecting some preference options crashed the app)\n + Version 0.9.8 preview 2 (alpha)\n @@ -548,7 +552,7 @@ * Changed password font\n * Allow to change Dropbox account\n * Fixed bug: Now remembering OTP password\n - * more to come\n + * Note: I have promised Material Design for this release. I am constantly working on it, but it needs a bit more time. Sorry! \n diff --git a/src/keepass2android/Resources/xml/preferences.xml b/src/keepass2android/Resources/xml/preferences.xml index 40992d98..40cccbd0 100644 --- a/src/keepass2android/Resources/xml/preferences.xml +++ b/src/keepass2android/Resources/xml/preferences.xml @@ -56,7 +56,7 @@ android:key="export_prefs" android:title="@string/export_prefs" > - + - + - + diff --git a/src/keepass2android/keepass2android.csproj b/src/keepass2android/keepass2android.csproj index 0e95e4ee..1dd379a9 100644 --- a/src/keepass2android/keepass2android.csproj +++ b/src/keepass2android/keepass2android.csproj @@ -42,14 +42,14 @@ True - none + full True bin\Release prompt 4 False False - armeabi,armeabi-v7a + armeabi;armeabi-v7a @@ -148,7 +148,6 @@ - @@ -772,9 +771,9 @@ - + Designer - + diff --git a/src/keepass2android/pluginhost/PluginListActivity.cs b/src/keepass2android/pluginhost/PluginListActivity.cs index c83dbe7d..6e2bdfaa 100644 --- a/src/keepass2android/pluginhost/PluginListActivity.cs +++ b/src/keepass2android/pluginhost/PluginListActivity.cs @@ -10,7 +10,7 @@ using Keepass2android.Pluginsdk; namespace keepass2android { [Activity(Label = "@string/plugins", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden)] - [IntentFilter(new[] { "keepass2android.PluginListActivity" }, Categories = new[] { Intent.CategoryDefault })] + [IntentFilter(new[] { "kp2a.action.PluginListActivity" }, Categories = new[] { Intent.CategoryDefault })] public class PluginListActivity : ListActivity { private PluginArrayAdapter _pluginArrayAdapter; diff --git a/src/keepass2android/search/SearchProvider.cs b/src/keepass2android/search/SearchProvider.cs index 54b16817..a70deeee 100644 --- a/src/keepass2android/search/SearchProvider.cs +++ b/src/keepass2android/search/SearchProvider.cs @@ -33,7 +33,7 @@ using System.Collections.Generic; namespace keepass2android.search { - [ContentProvider(new [] { SearchProvider.Authority }, Exported=false)] + [ContentProvider(new [] { SearchProvider.Authority}, Exported=false )] public class SearchProvider : ContentProvider { private enum UriMatches