diff --git a/CHOVY-GEN/CHOVY-GEN.vcxproj b/CHOVY-GEN/CHOVY-GEN.vcxproj new file mode 100644 index 0000000..9ef4309 --- /dev/null +++ b/CHOVY-GEN/CHOVY-GEN.vcxproj @@ -0,0 +1,163 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + 15.0 + {DCDBF747-DFB6-450E-A403-1C592D20EAEB} + Win32Proj + CHOVYGEN + 10.0.14393.0 + + + + DynamicLibrary + true + v141 + Unicode + + + DynamicLibrary + false + v141 + true + Unicode + + + DynamicLibrary + true + v141 + Unicode + + + DynamicLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + $(SolutionDir)CHOVY-TRANSFER\bin\$(Configuration) + CHOVY + + + true + + + false + + CHOVY + $(SolutionDir)CHOVY-TRANSFER\bin\$(Configuration) + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;CHOVYGEN_EXPORTS;%(PreprocessorDefinitions) + C:\openssl\include;%(AdditionalIncludeDirectories) + MultiThreaded + + + Windows + C:\openssl\lib;%(AdditionalLibraryDirectories) + ws2_32.lib;libsslMT.lib;Crypt32.lib;libcryptoMT.lib;%(AdditionalDependencies) + + + + + + + Level3 + Disabled + _DEBUG;_WINDOWS;_USRDLL;CHOVYGEN_EXPORTS;%(PreprocessorDefinitions) + + + Windows + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;CHOVYGEN_EXPORTS;%(PreprocessorDefinitions) + MultiThreaded + C:\openssl\include;%(AdditionalIncludeDirectories) + + + Windows + true + true + C:\openssl\lib;%(AdditionalLibraryDirectories) + ws2_32.lib;libsslMT.lib;Crypt32.lib;libcryptoMT.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + NDEBUG;_WINDOWS;_USRDLL;CHOVYGEN_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + true + + + + + + \ No newline at end of file diff --git a/CHOVY-GEN/CHOVY-GEN.vcxproj.filters b/CHOVY-GEN/CHOVY-GEN.vcxproj.filters new file mode 100644 index 0000000..dc521e5 --- /dev/null +++ b/CHOVY-GEN/CHOVY-GEN.vcxproj.filters @@ -0,0 +1,27 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/CHOVY-GEN/CHOVY-GEN.vcxproj.user b/CHOVY-GEN/CHOVY-GEN.vcxproj.user new file mode 100644 index 0000000..d9462ff --- /dev/null +++ b/CHOVY-GEN/CHOVY-GEN.vcxproj.user @@ -0,0 +1,13 @@ + + + + $(SolutionDir)CHOVY-TRANSFER\bin\$(Configuration)\CHOVY-TRANSFER.EXE + WindowsLocalDebugger + Mixed + + + $(SolutionDir)CHOVY-TRANSFER\bin\$(Configuration)\CHOVY-TRANSFER.EXE + WindowsLocalDebugger + Mixed + + \ No newline at end of file diff --git a/CHOVY-GEN/chovy-gen.c b/CHOVY-GEN/chovy-gen.c new file mode 100644 index 0000000..a7f6ac2 --- /dev/null +++ b/CHOVY-GEN/chovy-gen.c @@ -0,0 +1,289 @@ +//Project Chovy - __sce_ebootpbp generator by @dots_tb and motoharu +// With CBPS help especially: @SiliCart, @nyaaasen, @notzecoxao (and his friends?) + +//Check out motoharu's project: https://github.com/motoharu-gosuto/psvcmd56/blob/master/src/CMD56Reversed/F00D/GcAuthMgrService.cpp#L1102 +#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop) ) + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "key_vault.h" +PACK(typedef struct +{ + uint8_t r[0x1c]; + uint8_t s[0x1c]; +} ECDSA_SIG_0x1c); + +PACK(typedef struct sce_ebootpbp { + uint64_t magic; + uint32_t key_type;// set to 1 (maybe keytype?) + uint32_t type;// 03 - ps1, 02 - psp + uint8_t np_title[0x30]; + uint64_t aid; + uint64_t secure_tick; + uint64_t filesz; + uint64_t sw_ver; + uint8_t padding[0xf8]; + ECDSA_SIG_0x1c ebootpbp_hdr_sig; + ECDSA_SIG_0x1c NPUMDIMG_sig; + ECDSA_SIG_0x1c sceebootpbp_sig; +} sce_ebootpbp); + + +typedef struct pbp_hdr { + uint32_t magic; + uint32_t unk; + uint32_t sfo_offset; + uint32_t icon0_offset; + uint32_t icon1_offset; + uint32_t pic0_offset; + uint32_t pic1_offset; + uint32_t snd0_offset; + uint32_t data_psp_offset; + uint32_t data_psar_offset; +} pbp_hdr; + + +#define PSAR_SZ 0x1C0000 +#define WORK_BUF_SZ 0x7c0 + + +//based motoharu +__declspec(dllexport) int can_be_reversed_80C17A(const uint8_t* src, int some_size, uint8_t* iv, uint8_t* src_xored_digest) +{ + unsigned char src_xored[0x20]; + memcpy(src_xored, iv, 0x20); + + if (some_size > 0x20) + return 0x12; + + for(int i = 0; i < some_size; i++) + src_xored[i] = src[i] ^ iv[i]; + + int r0; + + SHA256_CTX sha256_ctx; + SHA256_Init(&sha256_ctx); + SHA256_Update(&sha256_ctx, src_xored, 0x20); + r0 = SHA256_Final(src_xored_digest, &sha256_ctx); + if(r0 != 1) + return 0x11; + + for(int i = 0; i < 0x20; i++) + iv[i] = src_xored_digest[i] ^ iv[i]; + + for(int i = 0; i < 0x20; i++) + { + if(iv[i] != 0xFF) + { + iv[i] = iv[i] + 1; + break; + } + + iv[i] = 0; + } + + return 0; +} + + +__declspec(dllexport) int f00d_KIRK0x22(const uint8_t *hash, ECDSA_SIG_0x1c *signature, int key_sel) { + + + uint8_t hmac_in[0x38]; + uint8_t hmac_hash_iv[0x38]; + memcpy(&hmac_in, hash, 0x1c); + memcpy(&hmac_in[0x1c], &keyvault_ec_privkey[key_sel], 0x1c); + + HMAC_CTX *hmac_ctx = HMAC_CTX_new(); + HMAC_Init_ex(hmac_ctx, &hmac_key_0x22, 0x40, EVP_sha256(), NULL); + HMAC_Update(hmac_ctx, &hmac_in, 0x1c << 1); + unsigned int len; + HMAC_Final(hmac_ctx, &hmac_hash_iv, &len); + HMAC_CTX_free(hmac_ctx); + + uint8_t sha256_out[0x40]; + int ret = 0; + do { + ret = can_be_reversed_80C17A(hash, 0x1c, hmac_hash_iv, &sha256_out[0]); + if(ret != 0 || (ret = can_be_reversed_80C17A(hash, 0x1c, hmac_hash_iv, &sha256_out[0x20])) != 0) + return 0; + + } while(ret != 0); + + //ECDSA + + BIGNUM *a = BN_bin2bn(keyvault_ec_a, 0x1c, NULL), + *b = BN_bin2bn(keyvault_ec_b, 0x1c, NULL), + *p = BN_bin2bn(keyvault_ec_p, 0x1c, NULL), + *order = BN_bin2bn(keyvault_ec_N, 0x1c, NULL), + *x = BN_bin2bn(keyvault_ec_Gx, 0x1c, NULL), + *y = BN_bin2bn(keyvault_ec_Gy, 0x1c, NULL), + *priv_key = BN_bin2bn(keyvault_ec_privkey[key_sel], 0x1c, NULL), + *m = BN_bin2bn(sha256_out, 0x3c, NULL); + + BN_CTX *bn_ctx = BN_CTX_new(); + BN_MONT_CTX *bn_mon_ctx = BN_MONT_CTX_new(); + BN_MONT_CTX_set(bn_mon_ctx, order, bn_ctx); + + EC_GROUP *curve = EC_GROUP_new_curve_GFp(p, a, b, bn_ctx); + EC_POINT *generator = EC_POINT_new(curve); + EC_POINT_set_affine_coordinates_GFp(curve, generator, x, y, bn_ctx); + EC_GROUP_set_generator(curve, generator, order, NULL); + + EC_KEY *eckey=EC_KEY_new(); + EC_KEY_set_group(eckey,curve); + EC_KEY_set_private_key(eckey, priv_key); + + + m = BN_bin2bn(sha256_out, 0x3c, NULL); + BN_mod(m, m, order, bn_ctx); + + + + //Generate R in order to get custom "random number" + BIGNUM *sig_r = BN_new(); + EC_POINT_mul(curve, generator, m, NULL, NULL, bn_ctx); + EC_POINT_get_affine_coordinates_GFp(curve, generator, sig_r, NULL, bn_ctx); + BN_nnmod(sig_r, sig_r, order, bn_ctx); + + //Generate M^-1 + BIGNUM *exp = BN_new(); + BIGNUM *minv = BN_new(); + + BN_set_word(exp, (BN_ULONG)2); + BN_sub(exp, order, exp); + BN_mod_exp_mont(minv, m, exp, order, bn_ctx, bn_mon_ctx); + + + ECDSA_SIG *sig = ECDSA_do_sign_ex(hash, 0x1c, minv, sig_r, eckey); + + + if(!sig) { + ret = 0; + goto error; + + } + BIGNUM *sig_s; + ECDSA_SIG_get0(sig, NULL, &sig_s); + BN_bn2bin(sig_r, &signature->r); + BN_bn2bin(sig_s, &signature->s); + ECDSA_SIG_free(sig); + //BN_free(sig_s); + ret = 1; + +error: + BN_free(sig_r); + + EC_POINT_free(generator); + BN_free(y); + BN_free(x); + BN_free(order); + BN_free(p); + BN_free(b); + BN_free(a); + BN_free(minv); + BN_free(exp); + BN_free(priv_key); + BN_CTX_free(bn_ctx); + BN_MONT_CTX_free(bn_mon_ctx); + return ret; + +} + + +__declspec(dllexport) int chovy_gen(char *ebootpbp, uint64_t signaid, char *outscefile) +{ + + int ret = 1; + FILE *fin = 0, *fout = 0; + + uint8_t *work_buf = (unsigned char*) calloc (1, WORK_BUF_SZ); + sce_ebootpbp *sceebootpbp_file = (unsigned char*) calloc (1, sizeof(sce_ebootpbp)); + + + fin = fopen(ebootpbp, "rb"); + if (!fin) { + + goto error; + } + memcpy(&sceebootpbp_file->magic, "NPUMDSIG", 0x8); + sceebootpbp_file->type = 2; + sceebootpbp_file->key_type = 1; + sceebootpbp_file->aid = signaid; + + + fseek(fin, 0, SEEK_END); + sceebootpbp_file->filesz = ftell(fin); + + pbp_hdr hdr; + fseek(fin, 0, SEEK_SET); + fread(&hdr, sizeof(pbp_hdr),1,fin); + + + fseek(fin, 0, SEEK_SET); + fread(work_buf, hdr.icon0_offset, 1,fin); + + uint8_t work_hash[0x1c]; + SHA256_CTX sha256_ctx; + SHA224_Init(&sha256_ctx); + SHA224_Update(&sha256_ctx, work_buf, hdr.icon0_offset); + SHA224_Final(work_hash, &sha256_ctx); + f00d_KIRK0x22(work_hash, &sceebootpbp_file->ebootpbp_hdr_sig, sceebootpbp_file->key_type); + + SHA224_Init(&sha256_ctx); + fseek(fin, hdr.data_psar_offset, SEEK_SET); + + size_t size = PSAR_SZ; + int to_read = size > WORK_BUF_SZ ? WORK_BUF_SZ : size; + + + fread(work_buf, to_read, 1,fin); + if(memcmp(work_buf, "NPUMDIMG", 0x8) == 0) + memcpy(&sceebootpbp_file->np_title, work_buf + 0x10, sizeof(sceebootpbp_file->np_title)); + else { + memcpy(&sceebootpbp_file->magic, "NPPS1SIG", sizeof(sceebootpbp_file->magic)); + sceebootpbp_file->type = 3; + } + + do { + size -= to_read; + SHA224_Update(&sha256_ctx, work_buf, to_read); + to_read = size > WORK_BUF_SZ ? WORK_BUF_SZ : size; + fread(work_buf, to_read, 1,fin); + } while(size > 0); + + SHA224_Final(work_hash, &sha256_ctx); + + f00d_KIRK0x22(work_hash, &sceebootpbp_file->NPUMDIMG_sig, sceebootpbp_file->key_type); + + SHA224_Init(&sha256_ctx); + SHA224_Update(&sha256_ctx, sceebootpbp_file, 0x1C8); + SHA224_Final(work_hash, &sha256_ctx); + + f00d_KIRK0x22(work_hash, &sceebootpbp_file->sceebootpbp_sig, sceebootpbp_file->key_type); + + fout = fopen(outscefile, "wb"); + if (!fout) { + goto error; + } + fwrite(sceebootpbp_file, 1, sizeof(sce_ebootpbp), fout); + + ret = 0; +error: + if (fin) + fclose(fin); + if (fout) + fclose(fout); + free(work_buf); + free(sceebootpbp_file); + return ret; +} diff --git a/CHOVY-GEN/key_vault.h b/CHOVY-GEN/key_vault.h new file mode 100644 index 0000000..2488e5e --- /dev/null +++ b/CHOVY-GEN/key_vault.h @@ -0,0 +1,17 @@ +uint8_t keyvault_ec_p[0x1c] = {0xA5, 0x3E, 0x11, 0x3E, 0x46, 0xD8, 0xC9, 0xC1, 0xF0, 0x9D, 0x9B, 0xCB, 0x2A, 0x53, 0x73, 0xD3, 0x79, 0xF6, 0x9D, 0xA2, 0x8D, 0x09, 0x99, 0x9F, 0xED, 0x57, 0xA9, 0x0F}; +uint8_t keyvault_ec_a[0x1c] = {0xA5, 0x3E, 0x11, 0x3E, 0x46, 0xD8, 0xC9, 0xC1, 0xF0, 0x9D, 0x9B, 0xCB, 0x2A, 0x53, 0x73, 0xD3, 0x79, 0xF6, 0x9D, 0xA2, 0x8D, 0x09, 0x99, 0x9F, 0xED, 0x57, 0xA9, 0x0C}; +uint8_t keyvault_ec_b[0x1c] = {0x90, 0x65, 0x94, 0x1D, 0x29, 0x37, 0x4A, 0x8F, 0x11, 0xDD, 0x1E, 0x54, 0x01, 0x89, 0x43, 0x4E, 0x4A, 0x6E, 0xBF, 0xAF, 0x54, 0x77, 0xF6, 0xC1, 0x72, 0xF6, 0x85, 0x5E}; +uint8_t keyvault_ec_N[0x1c] = { 0xA5, 0x3E, 0x11, 0x3E, 0x46, 0xD8, 0xC9, 0xC1, 0xF0, 0x9D, 0x9B, 0xCB, 0x2A, 0x52, 0x26, 0x98, 0xDE, 0xEF, 0x58, 0xDB, 0x1A, 0xD9, 0xAB, 0x7F, 0x04, 0xE3, 0xAE, 0x7F}; +uint8_t keyvault_ec_Gx[0x1c] = {0x7E, 0x06, 0x09, 0x82, 0x47, 0xE6, 0xB5, 0x9F, 0x31, 0x10, 0xBC, 0xBB, 0x3A, 0xB6, 0xC2, 0x50, 0xBC, 0x5A, 0xB0, 0x6C, 0x03, 0x2D, 0xAD, 0x43, 0x68, 0x4C, 0x24, 0x8F}; +uint8_t keyvault_ec_Gy[0x1c] = {0x0B, 0xD9, 0x41, 0x8D, 0xE8, 0xE3, 0xE4, 0x5D, 0x2D, 0x70, 0x1E, 0x02, 0x37, 0xFD, 0x7F, 0x2A, 0xDE, 0x0D, 0x48, 0xB7, 0x4C, 0xEE, 0xF2, 0xF1, 0xC8, 0xAC, 0x48, 0x4E}; +uint8_t keyvault_ec_pubkey[2][0x38] = { + {0x5F, 0x9D, 0x17, 0x1A, 0x2B, 0xDD, 0xA8, 0xD4, 0x08, 0x78, 0xBF, 0x98, 0x5A, 0xC3, 0x26, 0xED, 0x5E, 0xFF, 0x43, 0xC9, 0x37, 0x6C, 0x77, 0xEC, 0x0A, 0x00, 0xC7, 0xBB, 0xA3, 0x44, 0xE4, 0x4E, 0x6E, 0xAC, 0x25, 0x52, 0x35, 0xF9, 0x54, 0xF5, 0xB6, 0x17, 0xC7, 0xBD, 0x49, 0xF1, 0x80, 0x26, 0x24, 0x54, 0xAA, 0xE1, 0xB6, 0x2A, 0x9F, 0x2C}, + {0x67, 0x00, 0x2D, 0x9B, 0xB8, 0xE4, 0x2D, 0x2B, 0xF9, 0x61, 0x0B, 0x27, 0xFE, 0xAB, 0x9B, 0x34, 0x56, 0x15, 0x50, 0x92, 0x13, 0x12, 0xDF, 0xEE, 0x7A, 0x3A, 0x86, 0xEC, 0x6C, 0xA7, 0x14, 0x42, 0x6F, 0x6D, 0x4E, 0x96, 0x09, 0xA6, 0x38, 0xBF, 0x4A, 0xFB, 0x18, 0x2B, 0xFA, 0x50, 0xC8, 0x2F, 0xF2, 0xB4, 0xC5, 0xEC, 0x6C, 0xCD, 0x97, 0x65} + }; + +uint8_t keyvault_ec_privkey[2][0x1c] = { + {0x76, 0x74, 0x36, 0xA6, 0x99, 0x9D, 0x88, 0x48, 0x0E, 0xC8, 0x56, 0xF5, 0x5C, 0xEA, 0xBB, 0x43, 0x96, 0x85, 0x9E, 0x37, 0x45, 0x99, 0x40, 0x39, 0x21, 0xF5, 0x55, 0x98}, + {0x60, 0x7A, 0x2E, 0x55, 0x68, 0xB4, 0xB9, 0xA0, 0x32, 0xF4, 0x52, 0x53, 0xCF, 0xED, 0x20, 0xDB, 0x2E, 0x6E, 0x44, 0x6C, 0x37, 0x82, 0xE8, 0x2A, 0x1A, 0xB9, 0xC9, 0x23} + }; + +uint8_t hmac_key_0x22[0x40] = {0x54, 0x88, 0xA9, 0x81, 0x1C, 0x9A, 0x2C, 0xBC, 0xCC, 0x59, 0x6B, 0x1F, 0xAD, 0x1A, 0x7E, 0x29, 0xE0, 0x75, 0x84, 0x0F, 0x47, 0x43, 0x1F, 0x37, 0xAC, 0x06, 0x02, 0x46, 0x4A, 0x27, 0x9E, 0x02, 0xDF, 0x2E, 0x71, 0x65, 0xF1, 0x13, 0x7B, 0xF6, 0x9A, 0xE6, 0xDC, 0xB9, 0xDC, 0x38, 0x8C, 0x9D, 0xCC, 0xB3, 0x64, 0xC4, 0xCA, 0x26, 0xCB, 0x8F, 0x1A, 0xF0, 0x63, 0x8A, 0x6E, 0xAD, 0xB5, 0x4D}; diff --git a/CHOVY-TRANSFER.sln b/CHOVY-TRANSFER.sln new file mode 100644 index 0000000..61b3e78 --- /dev/null +++ b/CHOVY-TRANSFER.sln @@ -0,0 +1,48 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26228.76 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CHOVY-TRANSFER", "CHOVY-TRANSFER\CHOVY-TRANSFER.csproj", "{B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CHOVY-GEN", "CHOVY-GEN\CHOVY-GEN.vcxproj", "{DCDBF747-DFB6-450E-A403-1C592D20EAEB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Debug|x64.ActiveCfg = Debug|Any CPU + {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Debug|x64.Build.0 = Debug|Any CPU + {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Debug|x86.ActiveCfg = Debug|Any CPU + {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Debug|x86.Build.0 = Debug|Any CPU + {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Release|Any CPU.Build.0 = Release|Any CPU + {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Release|x64.ActiveCfg = Release|Any CPU + {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Release|x64.Build.0 = Release|Any CPU + {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Release|x86.ActiveCfg = Release|Any CPU + {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C}.Release|x86.Build.0 = Release|Any CPU + {DCDBF747-DFB6-450E-A403-1C592D20EAEB}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {DCDBF747-DFB6-450E-A403-1C592D20EAEB}.Debug|Any CPU.Build.0 = Debug|Win32 + {DCDBF747-DFB6-450E-A403-1C592D20EAEB}.Debug|x64.ActiveCfg = Debug|x64 + {DCDBF747-DFB6-450E-A403-1C592D20EAEB}.Debug|x64.Build.0 = Debug|x64 + {DCDBF747-DFB6-450E-A403-1C592D20EAEB}.Debug|x86.ActiveCfg = Debug|Win32 + {DCDBF747-DFB6-450E-A403-1C592D20EAEB}.Debug|x86.Build.0 = Debug|Win32 + {DCDBF747-DFB6-450E-A403-1C592D20EAEB}.Release|Any CPU.ActiveCfg = Release|Win32 + {DCDBF747-DFB6-450E-A403-1C592D20EAEB}.Release|Any CPU.Build.0 = Release|Win32 + {DCDBF747-DFB6-450E-A403-1C592D20EAEB}.Release|x64.ActiveCfg = Release|x64 + {DCDBF747-DFB6-450E-A403-1C592D20EAEB}.Release|x64.Build.0 = Release|x64 + {DCDBF747-DFB6-450E-A403-1C592D20EAEB}.Release|x86.ActiveCfg = Release|Win32 + {DCDBF747-DFB6-450E-A403-1C592D20EAEB}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/CHOVY-TRANSFER/App.config b/CHOVY-TRANSFER/App.config new file mode 100644 index 0000000..a3f4642 --- /dev/null +++ b/CHOVY-TRANSFER/App.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/CHOVY-TRANSFER/CHOVY-TRANSFER.csproj b/CHOVY-TRANSFER/CHOVY-TRANSFER.csproj new file mode 100644 index 0000000..c981102 --- /dev/null +++ b/CHOVY-TRANSFER/CHOVY-TRANSFER.csproj @@ -0,0 +1,107 @@ + + + + + Debug + AnyCPU + {B4CAD2C0-BA54-46B6-A8D0-43A9C2390D3C} + WinExe + CHOVY_TRANSFER + CHOVY-TRANS + v4.5.2 + 512 + true + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + false + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + true + false + + + chovy-trans.ico + + + + ..\packages\BouncyCastle.1.8.5\lib\BouncyCastle.Crypto.dll + + + ..\packages\DotNetZip.1.13.4\lib\net40\DotNetZip.dll + + + + + + + + + + + + + + + + Form + + + CHOVYTRANSFER.cs + + + + + + + + + + CHOVYTRANSFER.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + + + \ No newline at end of file diff --git a/CHOVY-TRANSFER/CHOVYTRANSFER.Designer.cs b/CHOVY-TRANSFER/CHOVYTRANSFER.Designer.cs new file mode 100644 index 0000000..a231575 --- /dev/null +++ b/CHOVY-TRANSFER/CHOVYTRANSFER.Designer.cs @@ -0,0 +1,294 @@ +namespace CHOVY_TRANSFER +{ + partial class CHOVYTRANSFER + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CHOVYTRANSFER)); + this.driveLetterSrc = new System.Windows.Forms.ComboBox(); + this.pspFolder = new System.Windows.Forms.TextBox(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.cmaDir = new System.Windows.Forms.TextBox(); + this.driveLetterDst = new System.Windows.Forms.ComboBox(); + this.label2 = new System.Windows.Forms.Label(); + this.label1 = new System.Windows.Forms.Label(); + this.pspGames = new System.Windows.Forms.ListBox(); + this.label3 = new System.Windows.Forms.Label(); + this.transVita = new System.Windows.Forms.Button(); + this.progressBar = new System.Windows.Forms.ProgressBar(); + this.progressStatus = new System.Windows.Forms.Label(); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.SuspendLayout(); + // + // driveLetterSrc + // + this.driveLetterSrc.BackColor = System.Drawing.Color.DimGray; + this.driveLetterSrc.DisplayMember = "1"; + this.driveLetterSrc.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.driveLetterSrc.FlatStyle = System.Windows.Forms.FlatStyle.Popup; + this.driveLetterSrc.ForeColor = System.Drawing.Color.Lime; + this.driveLetterSrc.FormattingEnabled = true; + this.driveLetterSrc.Items.AddRange(new object[] { + "A:\\", + "B:\\", + "C:\\", + "D:\\", + "E:\\", + "F:\\", + "G:\\", + "H:\\", + "I:\\", + "J:\\", + "K:\\", + "L:\\", + "M:\\", + "N:\\", + "O:\\", + "P:\\", + "Q:\\", + "R:\\", + "S:\\", + "T:\\", + "U:\\", + "V:\\", + "W:\\", + "X:\\", + "Y:\\", + "Z:\\"}); + this.driveLetterSrc.Location = new System.Drawing.Point(74, 12); + this.driveLetterSrc.Name = "driveLetterSrc"; + this.driveLetterSrc.Size = new System.Drawing.Size(41, 21); + this.driveLetterSrc.TabIndex = 1; + this.driveLetterSrc.SelectedIndexChanged += new System.EventHandler(this.driveLetterSrc_SelectedIndexChanged); + // + // pspFolder + // + this.pspFolder.BackColor = System.Drawing.Color.DimGray; + this.pspFolder.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.pspFolder.ForeColor = System.Drawing.Color.Lime; + this.pspFolder.Location = new System.Drawing.Point(121, 13); + this.pspFolder.Name = "pspFolder"; + this.pspFolder.Size = new System.Drawing.Size(194, 20); + this.pspFolder.TabIndex = 2; + this.pspFolder.Text = "PSP"; + this.pspFolder.TextChanged += new System.EventHandler(this.pspFolder_TextChanged); + // + // groupBox1 + // + this.groupBox1.BackColor = System.Drawing.Color.Black; + this.groupBox1.Controls.Add(this.cmaDir); + this.groupBox1.Controls.Add(this.driveLetterDst); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.driveLetterSrc); + this.groupBox1.Controls.Add(this.pspFolder); + this.groupBox1.ForeColor = System.Drawing.Color.Lime; + this.groupBox1.Location = new System.Drawing.Point(162, 12); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(622, 41); + this.groupBox1.TabIndex = 3; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Directories"; + // + // cmaDir + // + this.cmaDir.BackColor = System.Drawing.Color.DimGray; + this.cmaDir.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.cmaDir.ForeColor = System.Drawing.Color.Lime; + this.cmaDir.Location = new System.Drawing.Point(439, 14); + this.cmaDir.Name = "cmaDir"; + this.cmaDir.Size = new System.Drawing.Size(177, 20); + this.cmaDir.TabIndex = 6; + this.cmaDir.Text = "Users\\XXX\\Documents\\PS Vita"; + this.cmaDir.TextChanged += new System.EventHandler(this.cmaDir_TextChanged); + // + // driveLetterDst + // + this.driveLetterDst.BackColor = System.Drawing.Color.DimGray; + this.driveLetterDst.DisplayMember = "1"; + this.driveLetterDst.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.driveLetterDst.FlatStyle = System.Windows.Forms.FlatStyle.Popup; + this.driveLetterDst.ForeColor = System.Drawing.Color.Lime; + this.driveLetterDst.FormattingEnabled = true; + this.driveLetterDst.Items.AddRange(new object[] { + "A:\\", + "B:\\", + "C:\\", + "D:\\", + "E:\\", + "F:\\", + "G:\\", + "H:\\", + "I:\\", + "J:\\", + "K:\\", + "L:\\", + "M:\\", + "N:\\", + "O:\\", + "P:\\", + "Q:\\", + "R:\\", + "S:\\", + "T:\\", + "U:\\", + "V:\\", + "W:\\", + "X:\\", + "Y:\\", + "Z:\\"}); + this.driveLetterDst.Location = new System.Drawing.Point(392, 12); + this.driveLetterDst.Name = "driveLetterDst"; + this.driveLetterDst.Size = new System.Drawing.Size(41, 21); + this.driveLetterDst.TabIndex = 5; + this.driveLetterDst.SelectedIndexChanged += new System.EventHandler(this.driveLetterDst_SelectedIndexChanged); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(321, 16); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(65, 13); + this.label2.TabIndex = 4; + this.label2.Text = "CMA Folder:"; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(11, 16); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(63, 13); + this.label1.TabIndex = 3; + this.label1.Text = "PSP Folder:"; + // + // pspGames + // + this.pspGames.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64))))); + this.pspGames.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.pspGames.ForeColor = System.Drawing.Color.Lime; + this.pspGames.FormattingEnabled = true; + this.pspGames.Location = new System.Drawing.Point(162, 73); + this.pspGames.Name = "pspGames"; + this.pspGames.Size = new System.Drawing.Size(622, 223); + this.pspGames.TabIndex = 4; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.ForeColor = System.Drawing.Color.Lime; + this.label3.Location = new System.Drawing.Point(159, 56); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(82, 13); + this.label3.TabIndex = 5; + this.label3.Text = "Games on PSP:"; + // + // transVita + // + this.transVita.BackColor = System.Drawing.Color.Black; + this.transVita.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.transVita.ForeColor = System.Drawing.Color.Red; + this.transVita.Location = new System.Drawing.Point(649, 302); + this.transVita.Name = "transVita"; + this.transVita.Size = new System.Drawing.Size(135, 23); + this.transVita.TabIndex = 6; + this.transVita.Text = "MOV 1, PSVITA"; + this.transVita.UseVisualStyleBackColor = false; + this.transVita.EnabledChanged += new System.EventHandler(this.transVita_EnabledChanged); + this.transVita.Click += new System.EventHandler(this.transVita_Click); + // + // progressBar + // + this.progressBar.Location = new System.Drawing.Point(202, 297); + this.progressBar.Name = "progressBar"; + this.progressBar.Size = new System.Drawing.Size(441, 23); + this.progressBar.TabIndex = 7; + // + // progressStatus + // + this.progressStatus.AutoSize = true; + this.progressStatus.ForeColor = System.Drawing.Color.Lime; + this.progressStatus.Location = new System.Drawing.Point(159, 307); + this.progressStatus.Name = "progressStatus"; + this.progressStatus.Size = new System.Drawing.Size(21, 13); + this.progressStatus.TabIndex = 8; + this.progressStatus.Text = "0%"; + // + // pictureBox1 + // + this.pictureBox1.BackgroundImage = global::CHOVY_TRANSFER.Properties.Resources.chovytrans; + this.pictureBox1.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch; + this.pictureBox1.Location = new System.Drawing.Point(9, 3); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(144, 317); + this.pictureBox1.TabIndex = 9; + this.pictureBox1.TabStop = false; + // + // CHOVYTRANSFER + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.BackColor = System.Drawing.Color.Black; + this.ClientSize = new System.Drawing.Size(796, 332); + this.Controls.Add(this.pictureBox1); + this.Controls.Add(this.progressStatus); + this.Controls.Add(this.progressBar); + this.Controls.Add(this.transVita); + this.Controls.Add(this.label3); + this.Controls.Add(this.pspGames); + this.Controls.Add(this.groupBox1); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "CHOVYTRANSFER"; + this.Text = "Chovy-Transfer"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.CHOVYTRANSFER_FormClosing); + this.Load += new System.EventHandler(this.CHOVYTRANSFER_Load); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private System.Windows.Forms.ComboBox driveLetterSrc; + private System.Windows.Forms.TextBox pspFolder; + private System.Windows.Forms.GroupBox groupBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox cmaDir; + private System.Windows.Forms.ComboBox driveLetterDst; + private System.Windows.Forms.ListBox pspGames; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Button transVita; + private System.Windows.Forms.ProgressBar progressBar; + private System.Windows.Forms.Label progressStatus; + private System.Windows.Forms.PictureBox pictureBox1; + } +} + diff --git a/CHOVY-TRANSFER/CHOVYTRANSFER.cs b/CHOVY-TRANSFER/CHOVYTRANSFER.cs new file mode 100644 index 0000000..34afe16 --- /dev/null +++ b/CHOVY-TRANSFER/CHOVYTRANSFER.cs @@ -0,0 +1,519 @@ +using Microsoft.Win32; +using System; +using System.IO; +using System.Windows.Forms; +using Param_SFO; +using System.Runtime.InteropServices; +using System.Text; +using KeyDerivation; +using PSVIMGTOOLS; +using System.Drawing; + +namespace CHOVY_TRANSFER +{ + public partial class CHOVYTRANSFER : Form + { + [DllImport("CHOVY.dll", CallingConvention = CallingConvention.Cdecl)] + private static extern int chovy_gen(string ebootpbp, UInt64 AID, string outscefile); + + public string GetCmaDir() + { + string Dir = ""; + try + { + //try qcma + Dir = Registry.CurrentUser.OpenSubKey(@"Software\codestation\qcma").GetValue("appsPath").ToString(); + } + catch (Exception) + { + try + { + //try sony cma + Dir = Registry.CurrentUser.OpenSubKey(@"Software\Sony Corporation\Content Manager Assistant\Settings").GetValue("ApplicationHomePath").ToString(); + } + catch (Exception) + { + try + { + //try devkit cma + Dir = Registry.CurrentUser.OpenSubKey(@"Software\SCE\PSP2\Services\Content Manager Assistant for PlayStation(R)Vita DevKit\Settings").GetValue("ApplicationHomePath").ToString(); + } + catch (Exception) + { + try + { + string DefaultDir = Path.Combine(Environment.GetEnvironmentVariable("HOMEDRIVE"), Environment.GetEnvironmentVariable("HOMEPATH"), "Documents", "PS Vita"); + if (Directory.Exists(DefaultDir)) + { + Dir = DefaultDir; + } + } + catch (Exception) + { + //Do nothing + } + } + } + + } + + if (ReadSetting("CmaDir") != "") + { + Dir = ReadSetting("CmaDir"); + } + + return Dir.Replace("/","\\"); + } + + + public string ReadSetting(string Setting) + { + string Value = ""; + try + { + + RegistryKey key; + key = Registry.CurrentUser.CreateSubKey(@"Software\CHOVYProject\Chovy-Trans"); + Value = key.GetValue(Setting).ToString(); + key.Close(); + } + catch (Exception) { return ""; } + return Value; + } + + public void WriteSetting(string Setting, string Value) + { + try + { + RegistryKey key; + key = Registry.CurrentUser.CreateSubKey(@"Software\CHOVYProject\Chovy-Trans"); + key.SetValue(Setting, Value); + key.Close(); + } + catch (Exception) { } + } + + public void ChangeCmaDir(string newDir) + { + string DriveLetter = Path.GetPathRoot(newDir); + driveLetterDst.Text = DriveLetter; + cmaDir.Text = newDir.Remove(0, DriveLetter.Length); + } + + public void ChangePspDir(string newDir) + { + string DriveLetter = Path.GetPathRoot(newDir); + driveLetterSrc.Text = DriveLetter; + pspFolder.Text = newDir.Remove(0, DriveLetter.Length); + } + + public string FindPspDir() + { + for(char i = 'A'; i < 'Z'; i++) + { + if (Directory.Exists(Path.Combine(i + ":\\", pspFolder.Text))) + { + return Path.Combine(i + ":\\", pspFolder.Text); + } + } + return Path.Combine("D:\\",pspFolder.Text); + } + + public int ReadInt32(Stream s) + { + byte[] IntData = new byte[0x4]; + s.Read(IntData, 0x00, 0x4); + return BitConverter.ToInt32(IntData, 0x00); + } + + public void PopulatePspGameList() + { + string PspDir = Path.Combine(driveLetterSrc.Text, pspFolder.Text); + pspGames.Items.Clear(); + try + { + string[] games = Directory.GetFileSystemEntries(Path.Combine(PspDir, "GAME")); + + foreach (string game in games) + { + try + { + string EbootPbp = Path.Combine(game, "EBOOT.PBP"); + + + string TitleId = Path.GetFileName(game); + string Title = GetTitleFromPbp(EbootPbp); + string ContentId = GetContentIdFromPbp(EbootPbp); + + string LicenseFile = Path.Combine(PspDir, "LICENSE", ContentId); + + if (TitleId.Length == 9 && File.Exists(LicenseFile)); + { + pspGames.Items.Add(TitleId + " - " + Title); + } + + } + catch (Exception) { }; + + } + } + catch (Exception) { }; + + } + public string GetTitleFromPbp(string pbp) + { + byte[] SfoData = GetSfo(pbp); + + using (MemoryStream ms = new MemoryStream(SfoData, 0x00, SfoData.Length)) + { + PARAM_SFO sfo = new PARAM_SFO(ms); + return sfo.Title; + } + } + + public byte[] GetSfo(string pbp) + { + FileStream pbps = File.OpenRead(pbp); + pbps.Seek(0x08, SeekOrigin.Begin); + int sfoOffset = ReadInt32(pbps); + int sfoSize = ReadInt32(pbps); + + + + pbps.Seek(sfoOffset, SeekOrigin.Begin); + sfoSize -= (int)pbps.Position; + + byte[] SfoData = new byte[sfoSize]; + pbps.Read(SfoData, 0x00, sfoSize); + pbps.Dispose(); + return SfoData; + } + + public byte[] GetIcon0(string pbp) + { + FileStream pbps = File.OpenRead(pbp); + pbps.Seek(0x0C, SeekOrigin.Begin); + int sfoOffset = ReadInt32(pbps); + int iconSize = ReadInt32(pbps); + + + pbps.Seek(sfoOffset, SeekOrigin.Begin); + iconSize -= (int)pbps.Position; + + byte[] IconData = new byte[iconSize]; + pbps.Read(IconData, 0x00, iconSize); + pbps.Dispose(); + return IconData; + } + + public string GetContentIdFromPs1Pbp(string pbp) + { + FileStream pbps = File.OpenRead(pbp); + pbps.Seek(0x20, SeekOrigin.Begin); + Int64 PSPData = ReadInt32(pbps); + pbps.Seek(PSPData + 0x560, SeekOrigin.Begin); + byte[] ContentId = new byte[0x24]; + pbps.Read(ContentId, 0x00, 0x24); + pbps.Close(); + return Encoding.UTF8.GetString(ContentId); + } + + public bool IsPs1(string pbp) + { + FileStream pbps = File.OpenRead(pbp); + pbps.Seek(0x24, SeekOrigin.Begin); + Int64 NPUMDIMGOffest = ReadInt32(pbps); + pbps.Seek(NPUMDIMGOffest, SeekOrigin.Begin); + byte[] Header = new byte[0x8]; + pbps.Read(Header, 0x00, 0x8); + pbps.Close(); + if(Encoding.UTF8.GetString(Header) == "PSISOIMG") + { + return true; + } + else + { + return false; + } + + } + public string GetContentIdFromPbp(string pbp) + { + if(IsPs1(pbp)) + { + return GetContentIdFromPs1Pbp(pbp); + } + else + { + return GetContentIdFromPspPbp(pbp); + } + } + + public string GetContentIdFromPspPbp(string pbp) + { + FileStream pbps = File.OpenRead(pbp); + pbps.Seek(0x24, SeekOrigin.Begin); + Int64 NPUMDIMGOffest = ReadInt32(pbps); + pbps.Seek(NPUMDIMGOffest + 0x10, SeekOrigin.Begin); + byte[] ContentId = new byte[0x24]; + pbps.Read(ContentId, 0x00, 0x24); + pbps.Close(); + return Encoding.UTF8.GetString(ContentId); + } + + public CHOVYTRANSFER() + { + InitializeComponent(); + } + + private void CHOVYTRANSFER_Load(object sender, EventArgs e) + { + string PspDir = ReadSetting("PspFolder"); + if (PspDir != "") + { + pspFolder.Text = PspDir; + } + + ChangePspDir(FindPspDir()); + ChangeCmaDir(GetCmaDir()); + PopulatePspGameList(); + } + + private void pspFolder_TextChanged(object sender, EventArgs e) + { + WriteSetting("PspFolder", pspFolder.Text); + PopulatePspGameList(); + } + + private void driveLetterSrc_SelectedIndexChanged(object sender, EventArgs e) + { + PopulatePspGameList(); + } + + private void cmaDir_TextChanged(object sender, EventArgs e) + { + WriteSetting("CmaDir", Path.Combine(driveLetterDst.Text, cmaDir.Text)); + } + private void driveLetterDst_SelectedIndexChanged(object sender, EventArgs e) + { + WriteSetting("CmaDir", Path.Combine(driveLetterDst.Text, cmaDir.Text)); + } + private void transVita_EnabledChanged(object sender, EventArgs e) + { + Color red = Color.FromArgb(192, 0, 0); + Color black = Color.Black; + bool enabled = this.transVita.Enabled; + this.transVita.ForeColor = enabled ? red : black; + this.transVita.BackColor = enabled ? black : red; + } + + private void CHOVYTRANSFER_FormClosing(object sender, FormClosingEventArgs e) + { + Environment.Exit(0); + } + + private void transVita_Click(object sender, EventArgs e) + { + + if(!Directory.Exists(Path.Combine(driveLetterDst.Text, cmaDir.Text))) + { + MessageBox.Show("CMA Folder Doesn't Exist", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + if (!Directory.Exists(Path.Combine(driveLetterSrc.Text,pspFolder.Text))) + { + MessageBox.Show("PSP Folder Doesn't Exist", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + if (pspGames.SelectedIndex < 0) + { + MessageBox.Show("No PSP Game Selected", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + return; + } + + transVita.Enabled = false; + driveLetterDst.Enabled = false; + driveLetterSrc.Enabled = false; + pspFolder.ReadOnly = true; + cmaDir.ReadOnly = true; + pspGames.Enabled = false; + + string titleId = pspGames.SelectedItem.ToString().Substring(0, 9); + string gameFolder = Path.Combine(driveLetterSrc.Text, pspFolder.Text, "GAME", titleId); + string ebootFile = Path.Combine(gameFolder, "EBOOT.PBP"); + string cid = GetContentIdFromPbp(ebootFile); + string licenseFile = Path.Combine(driveLetterSrc.Text, pspFolder.Text, "LICENSE", cid + ".RIF"); + string sigFile = Path.Combine(gameFolder, "__sce_ebootpbp"); + string backupDir = Path.Combine(driveLetterDst.Text, cmaDir.Text); + + bool isPs1 = IsPs1(ebootFile); + + if (!File.Exists(licenseFile)) + { + MessageBox.Show("Could not find LICENSE file!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + transVita.Enabled = true; + driveLetterDst.Enabled = true; + driveLetterSrc.Enabled = true; + pspFolder.ReadOnly = false; + cmaDir.ReadOnly = false; + pspGames.Enabled = true; + return; + } + + FileStream rif = File.OpenRead(licenseFile); + byte[] bAid = new byte[0x08]; + rif.Seek(0x08, SeekOrigin.Begin); + rif.Read(bAid, 0x00, 0x08); + rif.Close(); + string sAid = BitConverter.ToString(bAid).Replace("-", "").ToLower(); + UInt64 uAid = BitConverter.ToUInt64(bAid, 0x00); + + if(File.Exists(sigFile)) + { + File.Delete(sigFile); + } + + int ChovyGenRes = chovy_gen(ebootFile, uAid, sigFile); + + if (!File.Exists(sigFile) || ChovyGenRes != 0) + { + MessageBox.Show("CHOVY-GEN Failed! Please check CHOVY.DLL exists\nand that the Microsoft Visual C++ 2015 Redistributable Update 3 RC is installed", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + transVita.Enabled = true; + driveLetterDst.Enabled = true; + driveLetterSrc.Enabled = true; + pspFolder.ReadOnly = false; + cmaDir.ReadOnly = false; + pspGames.Enabled = true; + return; + } + + /* + * BUILD PSVIMG FILE(s) + */ + + // Pacakge GAME + + byte[] CmaKey = CmaKeys.GenerateKey(bAid); + + string[] entrys = Directory.GetFileSystemEntries(gameFolder, "*", SearchOption.AllDirectories); + long noEntrys = entrys.LongLength; + string parentPath = "ux0:pspemu/temp/game/PSP/GAME/" + titleId; + int noBlocks = 0; + foreach (string fileName in Directory.GetFiles(gameFolder, "*", SearchOption.AllDirectories)) + { + noBlocks += Convert.ToInt32(new FileInfo(fileName).Length / PSVIMGConstants.PSVIMG_BLOCK_SIZE); + } + progressBar.Maximum = noBlocks; + + + string pgameFolder; + string pgameFolderl; + string scesys; + if (!isPs1) + { + pgameFolder = Path.Combine(backupDir, "PGAME", sAid, titleId, "game"); + pgameFolderl = Path.Combine(backupDir, "PGAME", sAid, titleId, "license"); + scesys = Path.Combine(backupDir, "PGAME", sAid, titleId, "sce_sys"); + } + else + { + pgameFolder = Path.Combine(backupDir, "PSGAME", sAid, titleId, "game"); + pgameFolderl = Path.Combine(backupDir, "PSGAME", sAid, titleId, "license"); + scesys = Path.Combine(backupDir, "PSGAME", sAid, titleId, "sce_sys"); + } + + Directory.CreateDirectory(pgameFolder); + Directory.CreateDirectory(pgameFolderl); + Directory.CreateDirectory(scesys); + + string psvimgFilepathl = Path.Combine(pgameFolderl, "license.psvimg"); + string psvimgFilepath = Path.Combine(pgameFolder, "game.psvimg"); + + string psvmdFilepathl = Path.Combine(pgameFolderl, "license.psvmd"); + string psvmdFilepath = Path.Combine(pgameFolder, "game.psvmd"); + + FileStream gamePsvimg = File.OpenWrite(psvimgFilepath); + gamePsvimg.SetLength(0); + PSVIMGBuilder builder = new PSVIMGBuilder(gamePsvimg, CmaKey); + + foreach (string entry in entrys) + { + string relativePath = entry.Remove(0, gameFolder.Length); + relativePath = relativePath.Replace('\\', '/'); + + bool isDir = File.GetAttributes(entry).HasFlag(FileAttributes.Directory); + + if (isDir) + { + builder.AddDir(entry, parentPath, relativePath); + } + else + { + builder.AddFileAsync(entry, parentPath, relativePath); + while (!builder.HasFinished) + { + try + { + int tBlocks = builder.BlocksWritten; + progressBar.Value = tBlocks; + decimal progress = Math.Floor(((decimal)tBlocks / (decimal)noBlocks) * 100); + progressStatus.Text = progress.ToString() + "%"; + } + catch (Exception) { } + + Application.DoEvents(); + } + } + } + + long ContentSize = builder.Finish(); + gamePsvimg = File.OpenRead(psvimgFilepath); + FileStream gamePsvmd = File.OpenWrite(psvmdFilepath); + PSVMDBuilder.CreatePsvmd(gamePsvmd, gamePsvimg, ContentSize, "game", CmaKey); + gamePsvmd.Close(); + gamePsvimg.Close(); + + + // Package LICENSE + FileStream licensePsvimg = File.OpenWrite(psvimgFilepathl); + licensePsvimg.SetLength(0); + builder = new PSVIMGBuilder(licensePsvimg, CmaKey); + builder.AddFile(licenseFile, "ux0:pspemu/temp/game/PSP/LICENSE", "/" + cid + ".rif"); + ContentSize = builder.Finish(); + + licensePsvimg = File.OpenRead(psvimgFilepathl); + FileStream licensePsvmd = File.OpenWrite(psvmdFilepathl); + PSVMDBuilder.CreatePsvmd(licensePsvmd, licensePsvimg, ContentSize, "license", CmaKey); + licensePsvmd.Close(); + licensePsvimg.Close(); + + // Write PARAM.SFO & ICON0.PNG + + byte[] ParamSfo = GetSfo(ebootFile); + byte[] Icon0 = GetIcon0(ebootFile); + File.WriteAllBytes(Path.Combine(scesys, "param.sfo"), ParamSfo); + File.WriteAllBytes(Path.Combine(scesys, "icon0.png"), Icon0); + + if(!isPs1) + { + MessageBox.Show("Success!\nYou can now Restore the game onto your PSVita from\n[Content Mannager] (Copy Content) -> (PC) -> (Applications) -> (PC -> This System) -> (PSP/Others)", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + else + { + MessageBox.Show("Success!\nYou can now Restore the game onto your PSVita from\n[Content Mannager] (Copy Content) -> (PC) -> (Applications) -> (PC -> This System) -> (PlayStation)", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + progressBar.Value = 0; + progressStatus.Text = "0%"; + + transVita.Enabled = true; + driveLetterDst.Enabled = true; + driveLetterSrc.Enabled = true; + pspFolder.ReadOnly = false; + cmaDir.ReadOnly = false; + pspGames.Enabled = true; + } + + } +} diff --git a/CHOVY-TRANSFER/CHOVYTRANSFER.resx b/CHOVY-TRANSFER/CHOVYTRANSFER.resx new file mode 100644 index 0000000..fb7c757 --- /dev/null +++ b/CHOVY-TRANSFER/CHOVYTRANSFER.resx @@ -0,0 +1,1517 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + AAABAAEAhpYAAAEAIADwRQEAFgAAACgAAACGAAAALAEAAAEAIAAAAAAAEDoBAMMOAADDDgAAAAAAAAAA + AAB/ACH/gAAh/4AAIv+BACP/ggAk/4MAJf+EACb/hAAn/4UAKP+GACn/hwAq/4gAK/+JACz/iQAt/4oA + Lv+LAC7/jAAv/4wAMP+NADH/jgAy/44AM/+PADP/kAA0/5AANf+RADb/kgA2/5MAN/+TADj/lAA5/5UA + Of+VADr/lgA7/5YAO/+XADz/lwA9/5gAPf+YAD7/mQA+/5kAP/+aAED/mgBA/5sAQP+bAEH/nABB/5wA + Qv+cAEL/nQBD/50AQ/+dAET/ngBE/54ARP+fAEX/nwBF/58ARf+fAEb/oABG/6AARv+gAEb/oABG/6AA + R/+gAEf/oQBH/6EAR/+hAEf/oQBH/6EAR/+hAEf/oQBI/6EAR/+hAEf/oQBH/6EAR/+hAEf/oQBH/6AA + R/+gAEf/oABH/6AARv+gAEb/oABG/58ARv+fAEX/nwBF/58BRf+eAUX/nQFF/5sAQv+bAED/nwBA/6QA + Q/+nAEf/qAZK/6cGSv+lBkn/pglK/6QFR/+lBkj/pQVH/6EAQf+fAD3/mwA6/5cAN/+UADf/lAA6/5QB + O/+VATv/lAA6/5QAOf+TADj/kgA3/5IAN/+RADb/kQA1/5AANP+PADP/jwAy/44AMv+NADH/jAAw/4wA + L/+LAC//igAt/4kALP+IACz/iAAr/4cAKv+GACn/hQAo/4UAJ/+DACb/gwAl/4IAJP+BACP/gAAi/38A + Iv+AACL/gQAj/4IAJf+DACX/hAAm/4UAKP+FACj/hgAp/4cAKv+IACv/iQAs/4oALf+KAC7/iwAv/4wA + MP+NADD/jQAx/44AMv+PADP/kAA0/5AANf+RADX/kgA2/5IAN/+TADj/lAA4/5QAOf+VADr/lQA7/5YA + O/+XADz/lwA9/5gAPf+YAD7/mQA//5oAP/+aAED/mwBA/5sAQf+bAEH/nABC/5wAQv+dAEP/nQBD/54A + RP+eAET/nwBE/58ARf+fAEX/nwBG/6AARv+gAEb/oABH/6EAR/+hAEf/oQBH/6EASP+hAEj/oQBI/6IA + SP+iAEj/ogBJ/6IASP+iAEn/ogBJ/6IASf+iAEn/ogBJ/6IASf+iAEn/ogBJ/6IASf+iAEj/ogBI/6IA + SP+iAEj/oQBI/6EASP+hAEf/oQFI/6ABR/+eAEb/nQBE/6AAQv+lAEX/qgVM/6gXVf+aKFj/gi5R/3Q8 + VP9pPlD/YDpK/1o3Rf9cPEn/XjpJ/2hEUv9tQ1T/e0FZ/4Y4V/+NLVL/nidX/6IZUP+gBEH/nQA7/5cA + Of+TADj/kwE6/5QBOv+UADj/kwA4/5IAN/+SADb/kQA1/5AANf+QADT/jwAz/44AMv+NADH/jQAw/4wA + MP+LAC//igAu/4kALf+JACz/iAAr/4cAKv+GACn/hQAo/4QAJ/+EACb/gwAm/4IAJP+BACP/gAAj/4EA + JP+CACX/gwAm/4QAJv+FACj/hgAo/4YAKf+HACv/iAAr/4kALP+KAC3/iwAu/4sAL/+MADD/jQAx/44A + Mv+PADL/jwAz/5AANP+RADX/kQA2/5IAN/+TADj/lAA4/5QAOf+VADr/lQA6/5YAO/+XADz/lwA9/5gA + Pf+ZAD7/mQA//5oAP/+aAED/mwBA/5sAQf+cAEL/nABC/50AQ/+dAEP/ngBE/54ARP+fAEX/nwBF/58A + Rv+gAEb/oABH/6AAR/+hAEf/oQBI/6EASP+iAEj/ogBI/6IASf+iAEn/owBJ/6MASf+jAEr/owBK/6MA + Sv+jAEr/owBK/6MASv+kAEr/owBK/6QASv+jAEr/owBK/6MASv+jAEr/owBK/6MASv+jAEr/owBK/6MA + Sv+iAUr/oQFJ/6AASP+gAET/pQBG/6sAS/+tEFX/oiRa/41AYf9kN0r/QTc7/yguK/8ZJB//FyEc/xsi + Hv8gJiL/Jikn/yksKv8qLyz/Ki8s/ygvK/8qMy7/LDUx/zE5Nf8+QkD/TERH/2Q8S/9+LUz/lR1M/6EO + R/+eADz/lQA2/5IAOP+UATr/lAA4/5MAN/+SADf/kQA2/5AANf+QADT/jwAz/48AMv+OADL/jQAx/4wA + MP+LAC//iwAu/4oALf+JACz/iAAr/4cAKv+HACn/hQAo/4UAJ/+EACb/gwAl/4IAJP+BACT/ggAl/4MA + Jv+EACf/hQAo/4YAKf+HACr/iAAr/4gALP+JACz/igAt/4sALv+MAC//jAAw/40AMf+OADL/jwAz/5AA + NP+QADX/kQA1/5IANv+SADf/kwA4/5QAOf+VADn/lQA6/5YAO/+XADz/lwA8/5gAPf+ZAD7/mQA//5oA + P/+aAED/mwBB/5wAQf+cAEL/nABC/50AQ/+eAET/ngBE/54ARf+fAEX/nwBG/6AARv+gAEf/oQBH/6EA + R/+hAEj/ogBI/6IASf+iAEn/ogBJ/6MASf+jAEr/owBK/6QASv+kAEv/pABL/6QAS/+kAEv/pABL/6QA + S/+lAEz/pQBM/6UATP+lAEz/pQBM/6UATP+lAEz/pQBM/6UATP+kAEz/pAFM/6QBTP+iAUv/oQBJ/6MA + SP+pAEr/rgNQ/64dXv+YJFj/dy9P/1E4Qv8uMC//GyYi/xkiHv8dHx7/JiIj/zcyM/9CPT7/S0VH/1ZP + Uf9cVFb/XVZY/1xWWP9bVlf/WVNV/1ZPUf9PSEr/Qz4//zUyMv8qKSn/Iygl/yQtKP8vMTD/TTlB/3g7 + Uv+bJFH/oAdB/5UANf+SADj/lAE5/5MAOP+TADf/kgA2/5EANf+QADT/kAA0/48AM/+OADL/jQAx/4wA + MP+LAC//iwAu/4oALf+JACz/iAAs/4cAKv+HACr/hgAp/4UAJ/+EACf/gwAm/4IAJf+DACb/hAAn/4UA + KP+GACn/hwAq/4gAK/+IACz/iQAt/4oALf+LAC//jAAv/40AMP+NADH/jgAy/48AM/+QADT/kQA1/5EA + Nv+SADf/kwA4/5MAOP+UADn/lQA6/5YAO/+WADv/lwA8/5gAPf+YAD7/mQA//5oAP/+aAED/mwBB/5wA + Qf+cAEL/nQBD/50AQ/+eAET/ngBE/58ARf+fAEX/oABG/6AAR/+hAEf/oQBH/6IASP+iAEj/ogBJ/6MA + Sf+jAEr/owBK/6MASv+kAEv/pABL/6QAS/+lAEz/pQBM/6UATP+lAEz/pQBN/6UATf+mAE3/pgBN/6YA + Tf+mAE3/pgBN/6YATf+mAE3/pgBN/6YATf+mAU3/pQFO/6QATf+jAEn/pgBJ/60ATf+xC1f/qRpa/5I0 + Xv9rOE7/QTo9/yIqJv8ZIx7/HiAe/yUjI/8lIiP/Hx0e/zAvL/9PTU3/OTY2/01JSv9UT1D/RUBC/0E8 + Pf9FQEH/TUtL/1NRUf9YVVX/W1ZX/19ZWv9hXl7/XVxb/1pXV/9PSkz/OzU2/yYjI/8YHBr/FiAc/y8u + Lf9oQU//nC9Z/58FP/+UADb/kgA5/5QBOf+TADf/kgA2/5EANv+RADX/kAA0/48AM/+OADL/jQAx/40A + MP+MAC//iwAv/4oALv+JAC3/iAAs/4gAK/+HACr/hgAp/4UAKP+EACf/gwAm/4QAJ/+FACj/hgAp/4cA + Kv+IACv/iQAs/4kALf+KAC7/iwAv/4wAMP+NADH/jgAy/48AMv+PADT/kAA0/5EANf+SADb/kgA3/5MA + OP+UADn/lQA6/5UAOv+WADv/lwA8/5cAPf+YAD7/mQA+/5oAP/+aAED/mwBB/5sAQf+cAEL/nQBD/50A + Q/+eAET/ngBE/58ARf+fAEb/oABG/6AAR/+hAEf/oQBI/6IASP+iAEn/owBJ/6MASv+jAEr/pABL/6QA + S/+kAEv/pQBM/6UATP+lAEz/pgBN/6YATf+mAE3/pgBN/6YATv+nAE7/pwBO/6cATv+nAE7/pwFP/6cA + T/+nAE//pwBP/6cBT/+mAU//pQBN/6YATP+qAEz/sQBS/7QTXf+mKGH/hTRY/1s1Rv8zMTL/GyUh/xYg + HP8dHx7/JCIj/yIfIP8YFhf/CwsL/wcHB/8SEhL/QUFB/2lpaf8jIiL/BAMD/xQSEv8YFhf/FhUV/xwZ + Gv8sKyv/ODY2/zs7Ov89PDz/PDs7/zs5Of89Ozv/Ozk5/0hFRf9XVFX/V1VV/0E+Pv8tKCn/HRoa/xEW + E/8nLCr/ZjZI/5wiUP+cADr/kgA2/5QBOv+TADj/kgA3/5IANv+RADX/kAA0/48ANP+OADL/jgAx/40A + Mf+MADD/iwAv/4oALv+JAC3/iAAs/4gAK/+HACr/hgAp/4UAKP+EACf/hQAo/4YAKf+HACr/iAAr/4kA + LP+JAC3/igAu/4sAL/+MADD/jQAx/44AMv+PADP/jwA0/5AANf+RADb/kgA2/5MAN/+TADj/lAA5/5UA + Ov+WADv/lgA8/5cAPP+YAD3/mQA+/5kAP/+aAD//mwBA/5sAQf+cAEL/nQBC/50AQ/+eAET/ngBF/58A + Rf+fAEb/oABG/6EAR/+hAEj/ogBI/6IASf+jAEn/owBK/6MASv+kAEv/pABL/6UATP+lAEz/pQBM/6YA + Tf+mAE3/pgBO/6cATv+nAE7/pwBP/6cAT/+nAE//qABP/6gAT/+oAE//qAFQ/6cAT/+mAE3/pwBO/6cB + UP+mAE7/pwBM/60AT/+0BFb/sA5a/58tYv96NlX/UT5H/yswLf8ZIx7/GB8c/yAhIP8kIiP/Hx0e/xMT + E/8JCQn/BgYG/wsMDP8VFRX/ISEh/ygoKP8nJyf/JiYm/ywsLP8lJib/EhIS/wsLC/8PDw//EhIS/xMT + E/8UFBT/FRUV/xUVFf8XFxf/FhYW/xMTE/8LCgr/CAYG/xQSEv8rKir/Kigo/yAfH/8rKSn/LCgp/xsX + GP8OFRH/MTAx/4A6Vf+jEEj/lAA1/5MBOv+UADj/kwA3/5IANv+RADX/kAA1/48ANP+OADP/jgAy/40A + Mf+MADD/iwAv/4oALv+KAC3/iQAs/4gAK/+HACr/hgAp/4UAKP+GACn/hwAq/4gAK/+JACz/igAt/4oA + Lv+MAC//jAAw/40AMf+OADL/jwAz/5AANP+QADX/kQA2/5IAN/+TADj/lAA4/5QAOf+VADr/lgA7/5cA + PP+XAD3/mAA+/5kAPv+aAD//mgBA/5sAQf+cAEL/nABC/50AQ/+eAET/ngBE/58ARf+gAEb/oABH/6EA + R/+hAEj/ogBI/6IASf+jAEr/owBK/6QAS/+kAEv/pQBM/6UATP+mAE3/pgBN/6YATf+nAE7/pwBO/6cA + T/+oAE//qABP/6gAUP+oAFD/qQBQ/6kAUP+pAFH/qQBR/6kBUf+pAE7/sgBU/7UQX/+yBVj/sABR/7YG + Wv+xH2T/mDRj/3FAVv9BLTb/Iisn/xYhHP8ZHhz/IiEh/yQgIv8cGRr/Dw8P/wcHB/8HBwf/Dg4O/xcX + F/8fHx//JCQk/ycnJ/8oKCj/KSkp/ysrK/8sLCz/LCws/y4uLv8yMjL/MDAw/yIiIv8YGBj/FBQU/xIS + Ev8SEhL/EhIS/xMTE/8WFhb/HR0d/ycoKP8uLi7/MDAw/ysrK/8hISH/GRkZ/xYWFv8fHx//Kioq/yom + J/8XFRX/EhsX/1pETf+gKFb/lwA1/5MBOf+UADn/kwA3/5IAN/+RADb/kAA1/48ANP+PADP/jgAy/40A + Mf+MADD/iwAv/4oALv+KAC3/iQAs/4gAK/+HACr/hgAp/4cAKv+IACv/iQAs/4oALf+LAC7/jAAv/4wA + MP+NADH/jgAy/48AM/+QADT/kQA1/5IANv+SADf/kwA4/5QAOf+VADr/lQA7/5YAO/+XADz/mAA9/5kA + Pv+ZAD//mgBA/5sAQf+bAEH/nABC/50AQ/+eAET/ngBE/58ARf+gAEb/oABG/6EAR/+hAEj/ogBI/6IA + Sf+jAEr/owBK/6QAS/+lAEv/pQBM/6UATf+mAE3/pgBN/6cATv+nAE7/pwBP/6gAT/+oAFD/qABQ/6kA + UP+pAFH/qQBR/6oAUf+qAFL/qgFS/6kCU/+oAVL/qgBP/7AbYf9+QV7/PzE4/3Y3Vv+XOmT/YTZK/zk0 + Nv8cKCL/Fh8b/x0hH/8jISL/IR8g/xcWFv8MDAz/BgYG/wkJCf8RERH/GRkZ/yAgIP8jIyP/JSUl/ycn + J/8oKCj/Kioq/ysrK/8rKyv/LCws/y0tLf8uLi7/MDAw/y8vL/8zMzP/PT09/zs7O/84ODj/Ojo6/0JC + Qv9RUVH/ampq/3R0dP9xcXH/YmJi/05OTv9CQkL/Pz8//zw8PP83Nzf/Li4u/yEhIf8aGhr/IiIi/y4s + Lf8mICH/DhMQ/zk0Nv+VL1f/mwA4/5IAOP+UADn/kwA4/5IAN/+RADb/kAA1/48ANP+PADP/jgAy/40A + Mf+MADD/iwAv/4oALv+KAC3/iQAs/4gAK/+HACr/iAAr/4kALP+KAC3/iwAu/4sAL/+MADD/jQAx/44A + Mv+PADP/kAA0/5EANf+RADb/kgA3/5MAOP+UADn/lQA6/5YAO/+XADz/lwA8/5gAPf+ZAD7/mgA//5oA + QP+bAEH/nABC/50AQv+dAEP/ngBE/58ARf+fAEb/oABG/6EAR/+hAEj/ogBI/6IASf+jAEr/pABL/6QA + S/+lAEz/pQBM/6YATf+mAE3/pwBO/6cATv+oAE//qABP/6kAUP+pAFD/qQBR/6kAUf+qAFL/qgBS/6oA + Uv+rAVP/qgFT/6kAUf+qAFD/rwBS/7UAVv+6HWn/RzlA/xEfGP8ZHBv/FBoX/x0nI/8YIBv/IB8f/yQh + Iv8fHR7/FBMT/woJCf8GBgb/CwsL/xMTE/8cHBz/ISEh/yIiIv8kJCT/JiYm/ycnJ/8oKCj/KSkp/ykp + Kf8pKSn/Kioq/ywsLP8tLS3/Li4u/zAwMP8xMTH/NDQ0/y8vL/82Njb/ODg4/zo6Ov88PDz/Pz8//0JC + Qv9DQ0P/QEBA/zw8PP87Ozv/Pj4+/0JCQv9HR0f/SEhI/0lJSf9FRUX/Pj4+/zU1Nf8lJSX/Hh8f/ykp + Kf8vKiv/FRUU/yYsKv+RPl//nQI8/5IAOP+UADn/kwA4/5IAN/+RADb/kQA1/5AANP+PADP/jgAy/40A + Mf+MADD/iwAv/4oALv+JAC3/iAAs/4gAK/+JACz/igAt/4oALv+LAC//jAAw/40AMf+OADL/jwAz/5AA + NP+RADX/kgA2/5IAN/+TADj/lAA5/5UAOv+WADv/lwA8/5cAPf+YAD7/mQA//5oAQP+bAED/mwBB/5wA + Qv+dAEP/ngBE/58ARP+fAEX/oABG/6EAR/+hAEj/ogBI/6IASf+jAEr/owBL/6QAS/+lAEz/pQBM/6YA + Tf+mAE7/pwBO/6cAT/+oAE//qABQ/6kAUP+pAFH/qgBR/6oAUv+rAFL/qwBT/6sCVP+qAVP/qQBS/6sA + Uf+yAFT/uQVc/7UVY/+fMWb/dzFS/0EuOP8YHRr/MS0v/y8uLv8lJCX/IyAh/xwaG/8REBD/CAgI/wcH + B/8NDQ3/FhYW/x0dHf8hISH/IiIi/yMjI/8lJSX/JiYm/ycnJ/8nJyf/KCgo/ygoKP8pKSn/Kioq/ysr + K/8sLCz/LCws/y0tLf8vLy//MTEx/zIyMv80NDT/NDQ0/zIyMv87Ozv/Ojo6/zo6Ov86Ojr/OTk5/zo6 + Ov87Ozv/Pj4+/0FBQf9CQkL/RUVF/z09Pf81NTX/NDQ0/0VFRf9NTU3/R0dH/0JCQv81NTX/JSQk/ygm + Jv8yLi7/GxgZ/yIsKP+OPl7/nQE7/5MBOf+VADn/kwA4/5IAN/+SADb/kQA1/5AANP+PADP/jgAy/40A + Mf+MADD/iwAv/4oALv+JAC3/iAAs/4kALf+KAC7/iwAv/4wAMP+NADH/jgAy/48AM/+QADT/kQA1/5IA + Nv+TADf/lAA4/5QAOf+VADv/lgA7/5cAPP+YAD3/mAA+/5kAP/+aAED/mwBB/5wAQv+cAEP/nQBD/54A + RP+fAEX/nwBG/6AAR/+hAEj/ogBI/6IASf+jAEn/owBK/6QAS/+lAEz/pQBM/6YATf+nAE7/pwBO/6cA + T/+oAFD/qQBQ/6kAUP+qAFH/qgBS/6oAUv+rAVP/qwFU/6oAU/+qAFH/rQBR/7QAVv+4Bl3/shlj/5gz + Zf9sP1X/PzI5/yAsJv8WIhz/HCAe/yYlJv8gICD/FRUV/w0NDf8HBwf/CAgI/w8PD/8XFxf/HR0d/yAg + IP8hISH/IiIi/yMjI/8kJCT/JiYm/yYmJv8mJib/Jycn/ygoKP8oKCj/KSkp/yoqKv8qKir/LCws/yws + LP8tLS3/Ly8v/zEwMf8yMjL/MzMz/zQ0NP84ODj/MTEx/zg4OP87Ozv/Ozs7/zw8PP8+Pj7/Pz8//0FB + Qf9AQED/Pj4+/0NDQ/8yMjL/JSUl/zk5Of9GRkb/OTk5/0dHR/9SUlL/Tk5O/0tLS/9CQkL/Ly4v/ycm + Jv8zMTH/Hhob/yMsKP+TOl7/mgA5/5QCOv+VADn/kwA4/5MAN/+SADb/kQA1/5AANP+PADP/jgAy/40A + Mf+MADD/iwAv/4sALv+JAC3/igAu/4sAL/+MADD/jQAx/44AMv+PADP/kAA0/5EANf+SADb/kwA3/5QA + OP+VADn/lQA6/5YAO/+XADz/mAA9/5kAPv+aAD//mgBA/5sAQf+cAEL/nQBD/54ARP+eAEX/nwBF/6AA + Rv+hAEf/oQBI/6IASf+jAEr/owBK/6QAS/+lAEz/pQBM/6YATf+mAE7/pwBO/6gAT/+oAFD/qQBQ/6kA + Uf+qAFH/qgBS/6sBU/+qAVP/qQBS/6kAUP+vAFL/twBZ/7kOYf+uKGj/jDNe/101SP81LjH/HCgi/xYf + G/8dIR//IyEi/yAeH/8VFBX/CQoK/wYGBv8JCQn/EBAQ/xgYGP8dHR3/Hx8f/yAgIP8hISH/IiIi/yIi + Iv8jIyP/JCQk/yUlJf8mJib/Jycn/ycnJ/8oKCj/KCgo/ykpKf8qKir/Kioq/ysrK/8sLCz/LC0t/y8u + Lv8xMTD/MzMy/zMzM/80NDT/NTU1/zk5Of82Njb/MzMz/zw8PP87Ozv/PT09/zU1Nf8rKyv/Kysr/zc3 + N/9BQUH/Q0ND/zIyMv9kZGT/g4OD/4uLi/9mZmb/ODg4/1hYWP9WVlb/VVVV/1JSUv9LS0v/OTk5/ykp + Kf8zMjL/HRsb/zE2M/+cKVf/lgA2/5UBO/+UADn/lAA4/5IAN/+SADb/kQA1/5AANP+PADP/jgAy/40A + Mf+MADD/iwAv/4oALv+LAC//jAAw/40AMf+OADL/jwAz/5AANP+RADX/kgA3/5MAN/+UADj/lQA5/5YA + Ov+WADz/lwA8/5gAPf+ZAD7/mgA//5oAQP+cAEH/nABC/50AQ/+eAET/nwBF/58ARv+gAEf/oQBH/6IA + SP+iAEn/owBK/6QAS/+kAEv/pQBM/6YATf+mAE7/pwBO/6gAT/+oAFD/qQBR/6oAUf+qAFL/qgFT/6oC + U/+pAFH/qwBR/7AAU/+5Alv/uRdm/6UpZf9+MFb/UjZE/y8xMP8YJR//FBwY/xsdHP8iICH/HRsc/xIR + Ev8JCQn/BgYG/woKCv8RERH/GRkZ/x0dHf8fHx//ICAg/yEhIf8iIiL/IiIi/yMjI/8jIyP/IyMj/yQk + JP8lJSX/JiYm/ycnJ/8nJyf/KCgo/ygoKP8pKSn/Kioq/yoqKv8rKyv/LCws/y8uLv8vLy7/Ly4v/yws + Lf8qKyz/Ly8x/zU0NP83Nzf/ODg4/zw8PP8yMjL/Ojo6/z8/P/8yMjL/JSUl/zo6Ov9ERET/Ozs7/zk5 + Of9FRUX/KSkp/2FhYf9YWFj/UVFR/2ZmZv9LS0v/VlZW/11dXf9eXV3/Xlxc/1taWv9TU1P/QUFB/y4u + Lv83MzT/GRoY/0o7Qf+jFk7/kwA3/5YBO/+VADn/kwA4/5MAN/+SADb/kQA1/5AANP+PADP/jgAy/40A + Mf+MADD/iwAv/4wAMP+NADH/jgAy/48AM/+QADT/kQA1/5IANv+TADf/lAA4/5UAOf+WADr/lgA8/5cA + Pf+YAD3/mQA+/5oAP/+bAEH/nABB/5wAQv+dAEP/ngBE/58ARf+gAEb/oABH/6EASP+iAEn/owBJ/6MA + Sv+kAEv/pQBM/6YATf+mAE3/pwBO/6cAT/+oAFD/qQBQ/6kAUf+pAVL/qQFS/6kAUP+rAFD/sQBT/7kG + Xv+0E2L/oC1l/3U3Vv9HNz//ISgl/xMgGv8bIB3/IiAg/yEfIP8aGBn/Dw4P/wcHB/8GBgb/DAwM/xQU + FP8aGhr/HR0d/x8fH/8fHx//ISEh/yEhIf8hISH/IiIi/yIiIv8iIiL/IyMj/yMjI/8kJCT/JSUl/yYm + Jv8mJib/Jycn/ycnJ/8oKCj/KSkp/ykpKf8rKyr/LSwr/y4tLP8qKiz/Jycp/yYnKf8xLy7/REA7/2Nb + Tv97cF7/Pzw5/zY2N/86Ojr/PT09/zk5Of82Njb/QEBA/zc3N/93d3f/goKC/3p6ev9fX1//MDAw/0VF + Rf85OTn/Kysr/0VFRf9hYWH/b29v/01NTf9XV1f/Xl5e/2RjY/9oZWX/Z2Vl/2FhYf9bW1v/R0dH/zIx + Mf82MTL/FyAc/3I7Uf+hBEH/lAE6/5YAOv+VADn/lAA4/5MAN/+SADb/kQA1/5AANP+PADP/jgAy/40A + Mf+MADD/jQAx/44AMv+PADP/kAA0/5EANf+SADb/kwA3/5QAOP+VADr/lgA6/5cAO/+XAD3/mAA+/5kA + P/+aAED/mwBB/5wAQv+dAEP/nQBD/54ARP+fAEX/oABG/6EAR/+hAEj/ogBJ/6MASv+kAEv/pQBL/6UA + TP+mAE3/pwBO/6cAT/+oAFD/qQFQ/6kBUf+oAFH/qABQ/6wAUP+0AFb/uAte/7EfZv+ZMmT/ajpR/z4z + OP8hKSX/FB8a/xodHP8jISL/IR8g/xcVFv8LCwv/BQUF/wcHB/8ODg7/FRUV/xsbG/8eHh7/ICAg/yEh + If8hISH/ICAg/yAgIP8gICD/IiIi/yIiIv8iIiL/IiIi/yMjI/8jIyP/JCQk/yUlJf8mJib/Jycn/ycn + J/8nJyf/KCgo/yoqKf8sKyr/Kyoq/yYnKP8jJCX/JyYm/zQyMP9MSEH/bWNU/4d7aP+Zi3P/n5F4/6aZ + f/9oYlb/MTIy/z49Pf89PT3/QEBA/zMzM/9BQUH/JiYm/1hYWP9UVFT/RkZG/0tLS/88PDz/Pz8//0lJ + Sf9FRUX/Q0ND/0xMTP9LS0v/T09P/1VVVf9cXFz/ZWVl/29tbf9xcHD/bm9v/2pqav9hYWH/SUlJ/zU1 + Nf8wKyz/JCwo/5YwWv+ZADj/lgE8/5UAOv+UADn/lAA4/5MAN/+SADb/kQA1/5AANP+PADP/jgAy/40A + Mf+OADL/jwAz/5AANP+RADX/kgA2/5MAN/+TADj/lQA5/5UAOv+WADv/lwA9/5kAPf+ZAD//mgA//5sA + Qf+cAEL/nQBD/54ARP+eAET/nwBG/6AAR/+hAEf/ogBI/6IASf+jAEr/pABL/6UATP+mAE3/pgBO/6cA + T/+oAVD/pwFQ/6YAT/+oAE7/rQBQ/7UAV/+3Dl//qSZk/4ctWP9aOkr/MC0v/xomIP8XIRz/HSAf/yIg + If8fHB3/ExIT/wkJCf8FBQX/CAgI/xAQEP8XFxf/HR0d/x4eHv8gICD/ICAg/yAgIP8hISH/ISEh/yEh + If8hISH/ISEh/yIiIv8iIiL/IiIi/yMjI/8jIyP/IyMj/yMjI/8kJCT/JSUl/yYmJv8nJyf/KSkp/yoq + Kf8oJyf/IiMk/yEhI/8nJyf/Ojcz/1hRR/94bl3/koVu/5+Rd/+klXv/opR8/5+TfP+fk3//pZmE/56T + ff8+Pjv/Ozs7/z4+Pv9CQkL/Ojo6/zs7O/85OTn/GRkZ/zMzM/9HR0f/VFRU/z8/P/9FRUX/RUVF/0lJ + Sf9MTEz/TExM/09PT/9SUlL/VFRU/1paWv9iYmL/b29v/3l5ef96enr/d3d3/3Nzc/9kZWX/SEZG/zw4 + Of8iJSL/TjZA/6UOSv+VADn/lwE8/5UAOv+UADn/lAA4/5MAN/+SADb/kQA1/5AANP+PADP/jgAy/48A + M/+QADT/kQA1/5EANv+SADf/lAA4/5QAOf+VADv/lgA7/5cAPf+YAD7/mQA//5oAQP+bAEH/nABC/50A + Q/+eAET/nwBF/58ARv+gAEf/oQBH/6IASf+jAEn/pABK/6QAS/+lAEz/pgBN/6YBTv+mAU//pQBN/6gA + Tf+uAFD/tgRZ/7QYYv+iL2b/gEJf/1E3Q/8rMC3/GiYg/xceGv8bHBv/IB0e/xsZGv8QDw//BwcH/wUF + Bf8KCgr/EhIS/xkZGf8eHh7/ICAg/yEhIf8iIiL/IiIi/x0dHf8fHx//ICAg/yAgIP8hISH/ISEh/yIi + Iv8iIiL/IiIi/yIiIv8jIyP/IyMj/yMjI/8kIyP/JSQk/ycnJ/8oJyf/Jycn/yQkI/8fHyD/Hx8g/ywr + Kv9EQTz/Zl9S/4V7av+bjnn/pJeC/6WYg/+iloH/oZaA/6OYg/+mnIb/qJ+K/6yjjv+tpZD/urKe/3Fu + ZP8zMzX/QkFB/0FBQf9DQ0P/NjU1/0NDQ/9BQUH/OTk5/z09Pf9AQED/RERE/0ZGRv9LS0v/Tk5O/1BQ + UP9SUlL/U1NT/1NTU/9WVlb/Wlpa/2BfX/9qamr/eHh4/4yMjP+RkZH/hYWF/4CAgP9nZmb/REJC/zo1 + Nv8iKyb/hzNV/50APP+WAT3/lgA8/5YAOv+VADn/kwA4/5IAN/+RADb/kAA1/5AANP+PADL/kAA0/5AA + Nf+RADb/kgA3/5MAOP+UADn/lQA6/5YAO/+XADz/mAA+/5kAP/+aAED/mwBB/5wAQv+dAEP/ngBE/58A + Rf+fAEb/oABH/6EASP+iAEn/owBK/6QAS/+lAUz/pQJN/6QBTf+kAEz/qABM/68AUP+2Clv/sB5j/5k4 + Zf9vO1T/RDg9/yUsKP8ZIx7/GiAd/yEgIP8gHR//GBcX/w0NDf8GBgb/BgYG/w0NDf8VFRX/Gxsb/x4e + Hv8gICD/ISEh/yEhIf8iIiL/HBwc/xwcHP8XFxf/Kysr/yMjI/8gICD/ISEh/yEhIf8iIiL/IiIi/yIi + Iv8iIiL/IyMj/yMjI/8kJCT/JiUl/yclJv8jJCb/ISAg/xsdHv8gICH/MS8t/1BNRf91bV7/k4h1/6Wa + hf+toYz/rKGM/6mfjP+poI3/rKOP/6+nkv+yqpX/ta2Z/7iwnf+6tKH/v7im/8G9qv/JxbL/vLmp/0NB + Q/8/Pz//QkJC/0ZGRv89PT3/Ozs7/0NDQ/9ERET/RERE/0VFRf9HR0f/S0tL/0NDQ/87Ozv/PDw8/0VF + Rf9RUVH/Wlpa/1laWv9dW1v/YV9f/2ZlZf9/f3//X19f/2FhYf+MjIz/bW1t/3x8fP9gYGD/QT9A/ywt + K/9ENzz/oxNO/5YAOf+XAT3/lgA7/5UAOv+UADn/kwA4/5IAN/+RADb/kAA1/48AM/+QADX/kQA2/5IA + N/+TADj/lAA5/5UAOv+WADv/lwA9/5gAPv+ZAD//mgBA/5sAQf+cAEL/nQBD/54ARP+fAEX/oABG/6AA + R/+hAEj/ogBJ/6MBSv+jAUv/ogBL/6MASv+oAEr/sABR/7MOWv+pHV7/jDRd/2I7Tf86ODn/Hyol/xch + HP8cHx7/IiAg/x8bHP8UEhP/CQkJ/wUFBf8ICAj/Dw8P/xYWFv8cHBz/Hx8f/yIiIv8iIiL/IiIi/yAg + IP8cHBz/ISEh/xsbG/8zMzP/PT09/0pKSv98fHz/Jycn/x8fH/8iIiL/IiIi/yIiIv8iIiL/IiIi/yMj + Iv8lJST/JiUk/yEiI/8cHB7/Gxob/yMjIv89OTT/YFpQ/4V+bP+imIP/r6aO/7ColP+yq5v/s6yb/7ev + nf+7tKL/v7mn/8O+rP/HwrL/yse2/8/NvP/S0sH/19bG/9rayv/b3s7/3uDP/9zezv/q7Nv/goJ7/zU1 + Nv9GRkb/RUVF/0ZGRv85OTn/RERE/0NDQ/9FRUX/SEhI/0lJSf8lJSX/Dw8P/woKCv8KCgr/ERER/yEh + If9ERET/X19f/2BeXv9jYWH/ZGNj/2dnZ/85OTn/UFBQ/2ZmZv8mJib/nZ2d/3x8fP9WVVT/QDs8/yMt + KP+DPVr/oQFA/5YBPf+XADz/lgA7/5UAOv+UADn/kwA4/5IAN/+RADb/kAA1/5EANf+SADf/kwA4/5QA + Of+VADr/lgA7/5cAPP+YAD3/mQA+/5oAQP+bAEH/nABC/50AQ/+eAET/nwBF/6AARv+hAEf/oQFJ/6EB + Sv+hAEn/ogBH/6gASv+wAVL/sRRc/6QuZP+DOVv/Vz1I/zAtLv8bJyH/GCAd/x4fH/8hHiD/Gxka/xAP + EP8HBwf/BQYG/wkJCf8RERH/GBgY/x0dHf8fHx//ISEh/yIiIv8hISH/HBwc/x0dHf8gICD/Jycn/y0t + Lf81NTX/RERE/01NTf9bW1v/VFRU/35+fv8kJCP/ISEh/yIiIv8iIiL/IyMi/yUlJP8jIyT/Hh4f/xkZ + G/8aGh3/Kygn/0lFP/9xbGD/lo18/6+nj/+6sZz/uLGh/7exov+9t6z/w7+0/8vJvf/Nyrz/0s/A/9fV + x//b28z/3+HR/+Ll1v/k6Nn/5era/+Xq2v/k6Nn/4+XW/9/i0//d3tD/2NjK/9jYyv+8u6//Q0NB/0RD + Rf9GRkf/S0tL/z8/P/9AQED/RkZG/0ZGRv9NTU3/ISEh/wEBAf8JCQn/DQ0N/w0NDf8GBgb/AQEB/woK + Cv9FRUX/ZWVl/2RjY/9jYmL/Dw8P/2ZmZv87Ozv/bGxs/2hoaP9nZ2f/mZmZ/3Nycv9MSUr/LzAv/0k8 + Qf+lE0//lwA7/5gBPv+XADz/lgA7/5UAOv+UADn/kwA4/5IAN/+RADX/kgA2/5MAOP+UADn/lQA6/5YA + O/+XADz/mAA9/5kAP/+aAD//mwBA/5wAQv+dAEP/ngBE/58ARf+fAUf/nwFH/58ARv+iAEb/qQBJ/68D + Uf+uGFz/mCVZ/3Y4VP9KNz//KTEu/xolIP8cIB3/IyEg/yEdH/8XFhf/DQ0N/wcHB/8HBwf/DAwM/xMT + E/8aGhr/HR0d/yAgIP8hISH/ISEh/yEhIf8gICD/HBwc/yAgIP83Nzf/NDQ0/xISEv8/Pz//cXFx/zw8 + PP9ra2v/SEhI/3BwcP81NDT/MC8v/yEiIv8kJCP/JCQk/yEhIv8cGx3/GBga/x4dHf8zMS7/VlJL/4F6 + av+km4f/uK+Z/722ov++t6v/vbis/8HAsv/NysD/1tXJ/9jay//Y28r/3d7N/+Pl1f/m6dr/5+vc/+ns + 3f/o69z/5eja/+Pl1v/f4tP/3N7P/9nZy//V1cb/0tLB/87Nvv/JyLr/xMKz/8rIt/9zcGr/Pj0+/0pK + Sf9LS0v/SkpK/zw8PP9ISEj/TU1N/zc3N/8CAgL/DAwM/w0NDf8TExP/HR0d/yoqKv8fHx//AwMD/xIS + Ev9hYWH/ZWVl/2tra/9SUlL/PT09/0VFRf9ycnL/T09P/1xcXP+vr6//ioqK/2JiYv9DPj//LDUw/4su + Vf+fAD7/mAE//5gAPf+XADz/lgA7/5UAOv+UADn/kwA3/5IANv+TADj/lAA4/5UAOv+WADv/lwA8/5gA + Pf+ZAD7/mgBA/5sAQP+cAEL/nQBD/54BRP+dAUX/nQBD/6AAQ/+oAEj/rgtT/6caWP+SN1//ajlP/0A2 + Ov8iKib/GCMe/xwgHv8gHh//Hhsd/xUTFP8LCgr/BgYG/wgICP8ODg7/FhYW/xsbG/8eHh7/ICAg/yAg + IP8hISH/ISEh/yEhIf8iIiL/Hh4e/yoqKv86Ojr/Jycn/zo6Ov9gYGD/MDAw/0ZGRv9LS0v/JSUl/zs6 + O/8wMDD/ISAg/yIhIf8fHh7/IB8g/xoaHP8YGRr/JCMh/0A7Nf9kXFT/ioNx/6uijP+4sJv/vbWh/7y2 + p/+/u7H/xsS4/9HPxf/Z2cr/39fM/9vUzP/f29L/7uff//jy6P/z8+f/5evb/+Xo2f/j5tf/4OLT/93e + 0P/a2s3/2NfJ/9XUxv/S0ML/zs2//8vJuv/Ixbb/xMGy/8G9rv+9uKr/wLqq/6Ofkf9GRUT/SkpK/0tL + S/9PT0//QEBA/0RERP9PT0//Jycn/wUFBf8JCQn/ERER/xgYGP8cHBz/KCgo/z8/P/8kJCT/AAAA/0dH + R/9sbGz/bGxs/1paWv8lJSX/a2tr/xgYGP+Wlpb/yMjI/6+vr/+fn5//f35+/1NQUP8xNTL/XT5K/6YI + Sv+XAD3/mQA+/5gAPf+XADz/lgA7/5UAOv+UADn/kgA3/5MAOP+VADn/lgA7/5cAPP+YAD3/mQA+/5oA + P/+bAED/nABB/50AQ/+dAUT/nABB/6QARP+tDFL/pCZd/4YyVv9eOkn/NzI0/x8oJP8ZIx//HSAf/yEf + IP8cGRv/ERAQ/wgICP8FBQX/CgoK/xAREf8XFxf/HBwc/x8fH/8gICD/ISEh/yEhIf8hISH/ICAg/yEh + If8hISH/IiIi/yIiIv8hISH/IyMj/05OTv9MTEz/X19f/zQ0NP9OTk7/MzMz/yYmJv8gICD/Hx8f/x8f + Hf8cHh7/GBoc/x4cHP8sKSf/SUU9/29oWv+TiXf/qqGN/7itlv+6sZ3/u7Of/8C6q//GwLf/z8y//9XV + xf/e3s7/4N/Q/83Gv/+AmpL/PIFv/zeBbf9Eh3T/a5qP/7zEv//v6eD/3N7P/9nZy//X1sj/1NPF/9LQ + w//Ozb//y8m7/8jGuP/FwrT/wr+w/8C8rf+9uKn/u7Wm/7mzo/+zrp//t7Kf/2tmYf9EREX/Tk5N/09P + T/9MTEz/QUFB/1FRUf8WFhb/Dw8P/yUlJf8wMDD/PDw8/0hISP9LS0v/Pz8//2ZmZv8XFxf/Li8v/3Nx + cf9samr/cXFx/3l5ef93d3f/enp6/6Ghof+5ubn/u7u7/66urv+VlJT/aGZm/0E+Pv87PDv/mRtQ/5sA + Pf+ZAUD/mQA+/5gAPf+XADz/lgA6/5UAOf+TADj/lAA5/5UAOv+WADz/lwA9/5gAPv+ZAD//mgBA/5sA + Qf+dAUP/mwBC/6EAQf+sFlX/kTRc/109S/8wMzL/GyYh/xkhHv8gIB//IR0e/xoXGP8ODQ7/BgYG/wYG + Bv8MDAz/ExMT/xkZGf8dHR3/ICAg/yEhIf8hISH/ISEh/yEhIf8hISH/ISEh/yIiIv8iIiL/IiIi/yIi + Iv8iIiL/IiIi/yMjI/8gICD/IiIi/z4+Pv8xMTH/IiAg/x8cHP8hISD/HyAh/x0dHv8aGxz/ICAh/zYy + L/9WUUf/fXNk/5mNfP+toIr/sqeR/7KplP+0rJj/ubKf/8C6qf/Hw7P/0M6+/9rYyv/d383/4+XU/+jr + 3f/Rx8f/YY+D/wp3Xv8QfGD/KoZx/0aSg/9lmZL/MYFu/4Olmv/n3tb/0NDB/87Nvf/Lyrr/yMe4/8bE + tf/DwLL/wr6v/8C7rP+9uKn/urWm/7ezo/+1sKD/s62c/66omf+xqZn/lo6B/0lHSP9PTk//T09P/1NT + U/9DQ0P/UVFR/yQkJP8pKSn/MjIy/z4+Pv9RUVH/YWFh/21tbf9jY2P/cnJy/1BQUP8rKyv/end3/3Bu + bv90cXH/dXNz/3l4eP+Ghob/mpqa/7S0tP/AwMD/ubm5/6Wlpf9/gID/UE1O/zM8N/+ANVT/owFD/5kB + QP+ZAD//mAA+/5cAPf+WADv/lQA6/5QAOf+VADr/lgA7/5cAPP+YAD7/mQA//5oAQP+cAEH/mwFD/5sA + P/+pCEz/mDlg/089Rf8cJiL/GB8c/x4dHf8eGxz/FRQU/wsLC/8FBQX/BwcH/w0NDf8UFBT/Ghoa/x0d + Hf8gICD/ISEh/yEhIf8hISH/ISEh/yEhIf8iIiL/IiIi/yIiIv8iIiL/IiIi/yIiIv8jIyP/IyMj/yMj + I/8jIyP/IiIi/yQkJP8mJSX/ISEh/yIgIP8iISL/HB0g/x0cHv8nJiX/QT02/2NcT/+Fe2f/npF8/6qb + hP+tn4n/raOO/66lkv+zq5j/u7Og/8K7qv/IxLT/z829/9jWx//f39D/5ebX/+bq2//p7t//6ubh/5Ok + nv8Kgmz/CKaq/wCGc/9ypJr/k7Sz/5e1tP9zqJ//E3xd/7G5s//b0sf/xMK0/8XBsv/Dv6//wL2u/766 + q/+9t6j/urWm/7eyo/+1r6D/sq2c/6+pmf+spZb/qqGT/6adj/+ono7/ZWBb/0tLS/9RUVH/VFRU/09P + T/9JSUn/Pz8//zQ0NP83Nzf/Tk5O/2dnZ/96enr/goKC/35+fv9ubm7/Wlpa/1RUVP95d3f/dHJy/3d1 + df96d3f/fHp6/39/f/+Pj4//rKys/8DAwP/AwMD/srKy/5SUlP9iYGD/OTw6/2BET/+lBkr/mQA//5oA + QP+ZAD//mAA9/5cAPP+WADv/lQA6/5YAO/+XADz/mAA9/5kAPv+aAED/mwBB/5oBQv+fAD//qR1Y/2Y5 + Tf8eKSX/EBQS/xgWF/8TERL/CQkJ/wYGBv8JCQn/Dw8P/xUVFf8bGxv/Hh4e/x8fH/8gICD/ICAg/yEh + If8hISH/ISEh/yIiIv8iIiL/IiIi/yIiIv8jIyP/IiIi/yMjI/8jIyP/IyMj/yMjI/8jIyP/JCQj/yUl + Jf8mJiX/JCQj/yAfIP8cHCD/IR8g/y8tK/9MRz7/b2dX/5CDcP+jlH3/p5qD/6ebh/+nn47/raed/7Cq + oP+zqpT/urOe/7+5qP/IxLP/z8y9/9bUxf/d3c7/4+TX/+fp2//p7N//5+vc/+nv3//i2tj/XpmK/wmE + aP8clIT/OJuM/3eso/+owsT/q8HB/4ewqv8Vg2P/X5eG/9/Nx//CvbH/wbuu/765qv+8t6j/urWm/7my + o/+1sKD/sa2c/66pmf+spZX/qqCS/6edj/+lmoz/oZaJ/6OYh/+Hf3L/TExM/1VTU/9UVFT/WVlZ/0dH + R/9VVVX/SUlJ/zg4OP9ZWVn/b29v/4GBgf+IiIj/g4OD/2dnZ/9jY2P/c3Jy/3Vzc/92dHT/eHd3/3p6 + ev99fHz/f39//4mJif+hoaH/urq6/8TExP+7u7v/o6Oj/3Z1df9DQUH/SEhH/58hV/+cAD7/mwFB/5oA + P/+ZAD7/mAA9/5cAPP+VADr/lwA8/5gAPf+ZAD7/mgA//5sAQf+aAUH/oQBB/6AtXf9EOT7/GSEc/zAs + Lf8iISH/BAQE/wsLC/8RERH/FxcX/xwcHP8eHh7/Hx8f/yAgIP8gICD/ICAg/yAgIP8gICD/ISEh/yEh + If8iIiL/IiIi/yIiIv8jIyP/IyMj/yMjI/8jIyP/IyMk/yMkI/8kJCT/JiUk/yUlJf8iIyP/Hh4g/xwd + H/8jIyP/OTUx/1pSSP98cWH/lop0/6SWf/+omoL/pJiC/6ediv+poZX/uLOu/8W+sv/JvKL/zcWj/8vI + wv/Rzcj/3NnJ/9fUxv/c283/4+TV/+fp2//p7N//6u3g/+nt3//m6dr/5unb/+HY1/+HsKX/AYVh/4K2 + q/+sycj/dLKp/6rIyP9sqJn/CZN9/xOnpP8giG3/t7uv/8i+sv+8tan/u7Sn/7myo/+2sKD/tK6e/7Gr + m/+tp5f/qqOU/6iekP+lm43/opmL/6CWiP+ek4X/m5CC/5yQf/9gXVj/UVFT/1hXVv9aWlv/U1NT/09P + T/9RUVH/JCQk/0FBQf9jY2P/dHR0/3Jycv9TU1P/UlJS/3Jycv92dXX/f319/4SCgv+Dg4P/g4OD/4GB + gf+Dg4P/h4eH/5eXl/+ysrL/xMTE/8LCwv+vr6//iYmJ/09NTv87RUD/jzJa/6EAQP+bAkL/mwBA/5oA + P/+YAD7/lwA9/5YAO/+XADz/mAA+/5kAP/+bAED/mgFB/6EAQP+bK1v/NDY1/yEjIf8tKCn/NzU1/xsb + G/8WFhb/HBwc/x4eHv8fHx//ICAg/x8fH/8fHx//ICAg/yAgIP8hISH/ISEh/yEhIf8hISH/IiIi/yIi + Iv8iIiL/IyMj/yMjI/8jIyP/IyMj/yUlJf8mJib/JSQl/yIiIv8dHh7/HR4f/yopJv9EQDr/aF9Q/4d8 + aP+dkHj/ppiB/6aag/+kmID/o5iE/6ecif+soo7/saiU/8nCt//Msn//vpA9/7N6Ff+kaBj/eW98/05R + if+cmZj/5ujX/+7v4P/p7t//7PDj/+vv4v/p7N//5uja/+Hi1P/e3tD/3tvV/9PR0f8unYH/X7Ki/7rY + 2P+w0s//utPU/6DGw/8YloH/C52R/z2ag//Ix7//wLap/7ixpP+3r6L/tK6e/7KsnP+vqZn/rKSU/6qi + lP+onpH/ppuO/6OZi/+gloj/npOF/5uQgv+YjYD/m4+B/4B3bP9SUVL/WllZ/1paWv9fX1//TExM/11d + Xf9VVVX/Ojo6/zg3N/88Ozv/Ojo6/09PT/9zc3P/dnZ2/35+fv9hYWH/QUFB/1NTU/9wcHD/gICA/4KC + gv+JiYn/l5eX/6+vr//AwMD/xMTE/7i4uP+ZmZn/YF5f/zc/O/+ASGD/pgFG/5sBQv+bAEH/mgBA/5kA + P/+YAD7/lwA8/5gAPf+ZAD//mgBA/5oBQf+eAD//nilb/zc5OP8tLCv/UE1O/1lZWf8cHBz/HBwc/x8f + H/8eHh7/Hh4e/x8fH/8gICD/ICAg/yAgIP8hISH/ISEh/yEhIf8hISH/ISEh/yIiIv8iIiL/IiIi/yMj + Iv8jIyP/JSQk/yYmJf8jIyP/Hh8g/xwdHv8hICL/NDEu/1FMQ/90a1v/koZw/6OXf/+pnIb/p52G/6ac + h/+nnYr/rKKP/6+nlf+0rZr/urOf/7y2p//Mya//vset/5NjKP9uKgD/Qw8A/yYCAP8DAAD/AAAA/wAA + AP9OZmX/1/Dn//Hy5P/o7d7/5una/+Hj1f/e3tH/29rM/9bVx//V1cj/6Nvc/5DMvv9Ey6n/0vjz/9Tu + 6v+p0Mz/Z7Kl/xKQbv86nHz/2drZ/9nKw/+zrZ3/tq+g/7Gsnf+vqJj/qqOV/6aflP+moJb/pJmM/6OY + iv+hl4n/oJaI/52UhP+bkYL/mo+B/5eMfv+Xi3v/lol4/2JeWv9ZWFn/Xl1c/2FhYf9ZWVn/UlJS/2dn + Z/9ra2v/a2pq/2tpaf91c3P/e3t7/3V1df+Kior/VFRU/wYGBv8KCgr/DAwM/xAQEP9QUFD/ZmZm/2Ji + Yv9vb2//kZGR/8LCwv/Kysr/vLy8/6Wlpf9wbm//ODw6/2xPW/+oCE3/mwBB/5wAQv+bAEH/mgBA/5kA + Pv+YAD3/mQA+/5oAP/+bAUH/mwA+/6YZVf9MREj/NjU1/1tWV/+Mi4v/QUFB/xcXF/8fHx//Hh4e/x8f + H/8fHx//Hx8f/yAgIP8gICD/ICAg/yEhIf8hISH/ISEh/yEhIf8hISH/IiIi/yMjI/8lJST/JSQk/yIg + If8cHB//Gxwd/yUkJP88OTT/XlhM/4F2Zf+ajHX/pZZ//6mchv+pnoj/q6GN/66mkv+1rpr/vLai/8G9 + q//HxLP/zsu6/9TSwf/Y18f/5OPT/8vQvf8vOy3/FAsR/wUAA/8zNDb/UVZT/0xLSf8TExL/AQAA/wAA + Af9Ji47/5ezg/+Hh0//d3tD/2trM/9jXyf/V1Mb/0tDD/83Mvf/X0cf/2t3Z/7Xx5//J////k+fS/y2r + iv8Bkm3/JJ6B/9Xh4P/s3tv/tbCi/7Otnf+yrJz/sKmZ/6qkm/+xqZ//uLKd/7+5pf+3rpj/saeR/6mf + hf+dknz/mo6B/5uOgf+ZjH7/l4t9/5SJe/+Yi3z/fXRp/1dYWf9gYF//YWFg/2VlZf9SUlL/Y2Nj/2dn + Z/9ubW3/dXNz/3Z1df92dnb/lJSU/5SUlP8QEBD/ICAg/0BAQP9RUVH/LCws/ysrK/9lZWX/W1tb/1lZ + Wf9ZWVn/cXFx/8DAwP/IyMj/qqqq/4B+fv8+Pz7/W0pR/6YOUP+cAEL/nQFD/5wAQv+bAED/mgA//5gA + Pv+ZAD//mwBA/5kBQP+mBEj/bENV/zxBPv9IQUP/ampq/zg4OP8UFBT/ICAg/xwcHP8fHx//ICAg/yAg + IP8gICD/ICAg/yAgIP8hISH/ISEh/yEhIf8iIiL/IyMj/yMjI/8hISH/Hh0e/xkaHP8dHBz/LSso/0pF + Pv9vZ1j/j4Rw/6SYgf+roIn/raKK/62mmf+2r6b/u7ix/7izo//CvKr/ycSx/9DNvP/V1MT/29rM/9/h + 0v/k5tj/6evd/+js3v/5/u7/sLSy/wcDBf8AAAD/GBgW/2FfVv8NDQv/Ly0r/1tZVP8EBAT/BAIC/yku + Mf/BxL//393O/9bVyP/W1Mb/09HD/9DOwP/OzL7/zMm8/8bFtv/PyL7/6dzX//bx7//2+fj/5vHu/5zT + xv+2183/59jT/7Wwof+wq5z/sayb/7Cpmv+popX/uLGf/7WwrP+Khb3/W1rJ/01N1f9dW9n/hH/T/6Oc + tP+ilYP/l4l5/5iLfv+XiXv/lYh6/5WIev+RhHP/ZGFd/2BfYP9jY2P/aGho/11dXf9bW1v/bW1t/3Fv + b/92dHT/d3Z2/5SUlP+fn5//kZGR/xwcHP8wMDD/dnZ2/4aGhv+Ghob/WVlZ/1xcXP9fX1//WVlZ/zEx + Mf8QEBD/MzMz/7u7u/+6urr/iYeH/0ZGRP9PREj/pBFS/54AQ/+eAUT/nABD/5sAQf+aAED/mQA+/5oA + QP+aAUH/nwBA/5QnVv9FS0j/Rj9B/zQzM/8rLCz/EBAQ/yIiIv8gICD/GBgY/yAgIP8fHx//ICAg/yAg + IP8gICD/ISEh/yIiIv8kIyH/IiIi/yAgIv8bHB3/GRkb/x8fH/81MzD/WlJK/311Zv+ek3//r6SP/7Wr + lf+2rZn/tK2e/7izqf/Ewr//ysWz/83Do//Qx6f/2NS+/9zf1v/b3tb/4N/Q/+Tm1v/p6t3/6u3g/+vv + 4//s8OP/6e7i/+/x4//T3d3/NTo6/wIAAf8ODQz/SEZA/1NRT/9JRkL/VFFK/wQEBP8AAAD/AAAA/5CI + e//g283/z87B/9DOwP/OzL7/y8m7/8nHuf/Hxbf/xcO0/8K+sP+9uav/w72x/83GvP/Vy8L/2crA/8S5 + rv+vqZn/saua/7Crm/+tp5f/qqKW/6+lj/+ZlLH/NjbI/wEBy/9WVr3/iou0/z07v/8HBs3/JSTg/3h1 + 1f+ekYn/lId1/5OGev+ShXb/kIN2/5KFdf97cWb/X19h/2dmZv9oaGj/a2tr/1dXV/9tbGz/dXJy/3Z0 + dP+JiIj/n5+f/5SUlP+cnJz/Q0ND/zAwMP97e3v/mpqa/8rKyv99fX3/VlZW/2JiYv8tLS3/BwcH/xgY + GP8CAgL/LCws/6urq/+VlJT/SElI/0pGSP+nHlr/nwBC/54BRf+dAEP/nABC/5sAQf+aAD//mwBB/5oA + QP+lBkr/aExY/0NGRP8oJCX/FxcX/w0NDf8gICD/JSUl/yAgIP8bGxv/Gxsb/yAgIP8fHx//ICAg/yEh + If8gICD/Hh4f/xoaGv8bGRr/JiQj/0A8N/9lXlH/iX9u/6SZg/+xpY//tKmT/7Orlf+0rZr/ubKf/7+4 + pv/FwbT/08/A/9e5dv++kSL/toIJ/7aBC//BjyD/0q9Y/+3frv/s8un/6e7i/+vv4P/q7eH/6evf/+bp + 3P/j5tv/4+PT/+bq4v+anqL/FBgP/w4PEv8YGxj/TUtG/2hnYv82NTT/DQsP/zMwLv9lX1f/uKyn/9TQ + xP/Lybz/y8m7/8nHuv/Hxbf/xMO0/8C+r/+9uar/vbeq/7y3qv+4sqb/s66g/7Grmv+tqZf/ramY/6+p + mf+spZf/qaGT/6edkf+lmob/p6Gx/yor2P8AAM7/AwPV/05P0f+Kis//cXHJ/5aWwP8/P77/EQ3T/2Ze + 0v+Xinj/j4Fz/46Ccv+NgHD/joBw/4l7av9nZF//aGdm/2tpaf9wcHD/Y2Nj/2VkZP95d3f/enl5/5iY + mP+goKD/lpaW/5GRkf+EhIT/V1dX/39/f/+urq7/jo6O/1hYWP9gYGD/UVFR/xISEv8VFRX/Pz8//zk5 + Of8GBgb/SUlJ/6Kiov9KTEv/TURH/6gYWP+fAEP/nwFG/54ARP+dAEP/nABC/5oAQP+bAkL/nQA+/5su + Xf9QU1H/MSwt/xYVFf8PDw//IiEh/yoqKv8fHx//ISEh/yEhIf8ZGRn/Hh4e/yAgIP8hISH/ISAg/yMg + If8uKij/S0c+/3JpXP+Th3P/p5uE/66ji/+tpI7/raSQ/7Cnlf+0rJr/urKh/8C4p//Dvq7/xsKz/9PS + xP/jxXH/vIMA/7Z4AP+9ewD/v3oA/7ZzAP+bYAD/Y0IE/927aP/s7+X/5+rg/+Tn2v/j5dj/4ePV/9/g + 0//d3NH/3eTL/9+m5P9mKHH/EyEO/ysnKv9SUFT/dXR1/4iFgv8+OzT/kJGY/+3np//UzHv/yMbA/8fF + tv/Fw7X/wb+v/767rf+5tar/u7av/726s/+7t67/s6yf/7Otn/+zrJ7/sKqb/62nmP+qpJT/p6CR/6Wc + jf+imYv/nZOH/6qehv9vbtX/AADb/wAA4f8AAOL/AADi/wAA3/8AAN3/LSvY/8fGyP+dm7z/KiPY/4By + oP+PgWP/iXts/4l7av+IeGr/iXlp/3RqX/9naGj/bW1t/3BwcP9ycnL/X19f/3Z2dv9/f3//oKCg/25u + bv9CQkL/Pz8//1dXV/94eHj/a2tr/2BgYP9XV1f/XV1d/11dXf9VVVX/CQkJ/z09Pf9VVVX/dnZ2/2tr + a/9nZ2f/m5ub/01QT/9SRUr/qhNX/58ARP+gAUb/nwBF/54AQ/+cAEL/mwBB/5oBQf+lAUX/gEdf/ykw + LP8UERL/FBQU/yQkJP8qKSn/Hx8f/yEhIf8hISH/ICAg/x8fH/8ZGRn/ISEh/yEhIf8bHBz/OjYw/52Q + e/+pnIP/raCK/6ugi/+qoIz/raWQ/7Kqlv+2r53/vLSi/8C5qP/Ev7D/ycW3/8/MvP/S08n/5925/86Y + E/+8ewD/woEF/8WAAf+mbAT/WDwI/zopD/9UOQf/x30A/9eyXP/l6eD/4ODS/97f0v/d3ND/3NrP/9nX + zf/V1sr/19XK/82G0f+eSaz/yI3Q/9/j3v+WnZ7/i4+j/1lhhf+Wrbb/2tme/8W9if/BwLj/wb2u/7u4 + rv+9ubH/vrqx/8LDtP/Ewbf/wrqx/8G2r/+6taf/sK+e/6ajkv+pn5P/p56R/6SbjP+hl4n/n5SG/5yR + hP+WjH7/pJiG/09N2f8AAOz/QD7v/3x+1/8JCeX/BgXn/wcH4/8AAOD/ZWLa/9bUzP8fGdv/YVK2/41+ + YP+EdGb/hHRj/4NzYf+Dc2D/fGxb/2pnZf9wcHH/c3Fx/3l5ef9paWn/a2tr/4yMjP9ubm7/FBQU/xgY + GP8SEhL/Dw8P/0VFRf9sbGz/YGBg/19fX/9bW1v/WVlZ/1xcXP8hISH/OTk5/319ff+Ojo7/qqqq/35+ + fv+Yl5f/S1BN/1tET/+tDVb/nwBF/6AAR/+fAEb/ngBE/50AQ/+bAUL/mgA//6kTVP9OQEb/DxIQ/yIh + Iv8sLCz/KCgo/yEhIf8hISH/ISEh/yEhIf8gICD/ISEh/xwcHP8bGxv/ISEh/yEhIv8aGhr/eHFk/7Ko + lP+ro5D/s6yY/7iyn/+9t6b/w72u/8jEtf/Oy7z/09LE/9jZy//e39L/4uTV/+ft6f/r2KL/yYwA/8iF + AP/AegD/NykS/xQWGv9GNBL/TDsb/2FHGv/hlAL/0okA/9vHmf/Z3df/2NXK/9bUyv/V08j/09HG/9LP + xf/O0L//z9G//+DP1f+p1av/tNm1/7vP1f+Nmt7/n5a2/8XGwP/Bwrv/vbix/7u3qf+2s6f/v7qw/7+9 + s/+/t6z/rXqN/5lCbP+RLGH/lzFo/6NKeP+zeJL/s6Ke/6Cciv+ekoX/nJKE/5mOgf+XjH7/lop8/5KF + ev+bkHb/WVTU/w0N+/+nqP7////v/1RV5f8AAO//AQDq/wAA6f9AQd7/tbPV/wsD5f9lWLT/h3VW/39t + YP9+bVr/fWta/31pWf99Z1X/bmJY/3Nyc/93dHT/eXh4/3l5ef9lZWX/i4uL/y4uLv8QEBD/Pj4+/0RE + RP8iIiL/HBwc/2NjY/9fX1//XFxc/15eXv9WVlb/V1dX/01NTf9BQUH/eXl5/6CgoP9xcXH/ZGRk/52b + nP9DS0j/bERW/64FUv+gAEf/oQBI/6AARv+fAEX/ngBE/5wCQ/+cAD//pCNb/z9CQf84ODj/ODg4/ykp + Kf8jIyP/IiIi/x8fH/8bGxv/Hh4e/yEhIf8gICD/ISEh/xkZGf8fHx//IiIi/x0dHv8qKSb/rqmZ/8O+ + rf/FwrL/zcq8/9PSw//Z2cv/3t/R/+Hk1v/j6Nr/5une/+fp4P/l6N3/5erm/+batv/Rkwr/w38M/9CX + NP9vThv/ExUd/zgtGv9SQBX/W0kb/6d/FP/rnwH/1apL/9HV0//PzsH/zs3C/83LwP/Myb7/ysi9/8nG + u//GxLj/wcKz/8C8sP/AvrD/xsO1/8K+tv/Hv7D/ubOk/7awo/+1r6H/s62g/7Gqnv+pppb/va+p/6NH + eP9+AD3/gAA0/4IANP+EADr/hgBA/4cAR/+gMGv/r4SO/5aQfv+Th3r/kod4/5GEdv+PgnP/jH9x/46B + Zf99caD/Kyv//2hn/P+Wlv7/1tbu/09P5f8aGen/Pz/k/8DC2v9fXuH/HBX2/3pniv98aUv/eGVY/3dk + U/92Y1L/d2FR/3dhUP9vW0r/b21q/3p5ef95eXj/gIGB/2xsbP+CgoL/Nzc3/xcXF/9fX1//c3Nz/21t + bf9PT0//XFxc/19fX/9bW1v/NTU1/x8fH/8jIyP/PDw8/05OTv9KSkr/SUlJ/zo6Ov+Hh4f/lZOU/0BL + Rv+GMFf/qwBL/6IBSv+iAEj/oABH/58ARv+eAET/nAJE/6AAQf+XKlr/OEA9/z89Pv8zMzP/Jycn/yQk + JP8fHx//Jycn/y8vL/8iIiL/Hh4e/yEhIf8gICD/Hx8f/xoaGv8iIiL/JCQk/xUVFv9dW1X/2djI/9LR + w//a2cz/3d7Q/+Di1f/h5Nf/4uXY/+Lk2f/i4tr/4eHZ/97e1v/d3NT/3d/T/923W//NoE3/1KFF/9qV + Ff9ySgP/OSYC/yYYA/8+QD//gIp0/+izBf/iqz//ycrH/8bEt//Fwrf/xMC2/8G+sv++u63/u7er/7iz + qv+5tKr/ubWp/7axpP+xq57/rqia/6qkl/+qo5b/p6CT/6Wcj/+imY3/nZOH/6Whkf+4cpT/iQpK/5sx + Xf+vXn7/xqSz/6Q5af+OAD//kgBI/44ARv+gHWP/pnyE/4iAbv+LfG7/iXps/4l5a/+Hd2n/g3Rn/4p5 + Xf9jWbz/KSj//wQE//9DQ/v/paft/6Ki6P+dnur/UE70/xUQ//9lVbj/eWVH/3RfUP9zXk7/cF1M/3Bc + S/9wW0r/b1pJ/21VRP9pXVP/enx9/3x7e/+AgID/fX19/3V1df9ubm7/Hx8f/1lZWf92dnb/o6Oj/4eH + h/9WVlb/X19f/zY2Nv8UFBT/FhYW/w4ODv8ODg7/ODg4/0pKSv9CQkL/VlZW/6+vr/9/fn7/R0lH/6Ad + Wv+mAEn/owFL/6IASf+hAEj/oABG/58ARf+cAkT/ogBC/5IzXP84Qz7/QT4//zAwMP8mJib/JCQk/yUl + Jf9MTEz/YWFh/0xMTP8aGhr/Hx8f/yEhIf8hISH/HBwc/x0dHf8jIyL/JCMj/xcWFv+ioZj/5ubZ/9vc + z//g4dT/4eLV/+Dh1P/d4NP/3d7T/9zc1P/a2tL/2djQ/9bWy//U1dH/19C6/96iKv/YhQD/5ZUA/7J2 + Av9ELgL/iF0D/9WxFP/94Sf/97IA/9i1dP+9v73/wLmu/7y4rf+4s6j/tbCm/7Swpv+0sKr/t7St/62n + m/+hmYz/oJiL/6OZjf+glor/nZOH/5uRhf+akIP/mY+C/5iNgP+SiHn/qZyT/6IvbP+nXYH/6PLt//L8 + +f/azNP/voOc/54yWP+QI0r/hwA0/4kAO/+oPW7/i35u/4NyZf+EcmX/g3Bi/4BwXf9/bVz/fWpb/4Nv + Uv9tYJv/PTrp/w8O//8IBf//FhX//xcS//8zKOn/a1uV/3VfQv9vWUj/blhI/21XR/9sV0b/a1VE/2pU + Q/9pU0L/alRB/2ROP/92c3H/gICB/4CAgP+Hh4f/c3Nz/4iIiP91dXX/W1tb/4GBgf+QkJD/XV1d/1tb + W/9VVVX/ExMT/xcXF/80NDT/QkJC/yMjI/8iIiL/RERE/z09Pf+goKD/tbS0/2RnZf9fSVP/rwtY/6QA + Sv+kAEv/owBK/6IASP+hAEf/oABG/50BRP+lAEX/hiVQ/zZBPP9DQEH/MDAw/yQkJP8rKyv/HBwc/x8f + H/9CQkL/Xl5e/y0tLf8kJCT/ICAg/yAgIP8hISH/Ghoa/yAgIP8kJCT/HBwc/zc2Nf/V1cr/39/U/9vc + z//b3ND/2tvO/9jZzP/X18z/1tXN/9TUzP/U0sj/0tDG/9HOwf/Nzsn/z8m1/9utTP/kmgT/75sA//ui + AP//qAD//6gA//2pAP/ls07/vLiu/7ayqP+0rqP/rame/7GpoP+vqqT/t7Kq/7erpP+3o53/saWd/7ey + qf+qoJb/louA/5aLf/+ZjoP/l4yA/5aLf/+ViX3/lIh7/5CFdv+ekoX/qDRw/5gRT//m1t7//u33/+2m + zf/GVo//smR+/9fQzf/Itbb/to+X/6EpXv+Pb2r/fGxb/31pXf97aFn/e2hX/3lnVf91YlH/cl1O/3pj + Qv98aE//dWR0/21cjv9oWIr/cV9y/3ZhSf9vWDb/aVRE/2lURP9pUkH/aVJA/2hRQP9mUD//ZlA//2VP + P/9mUED/Yko5/2ldVP+DhYb/g4KC/4iIiP+EhIT/d3d3/5ubm/+Tk5P/dHR0/1RUVP9VVVX/VFRU/1VV + Vf8XFxf/MTEx/2xsbP+EhIT/iIiI/0NDQ/8+Pj7/np6e/8bGxv+cmZv/T1hT/4hCY/+vAVH/pAFN/6UA + TP+kAEr/ogBJ/6EASP+gAEb/nQFF/6YARv+KNlv/ND86/0JAQf8wMDD/JCQk/yUlJf8kJCT/EBAQ/xYW + Fv8ZGRn/Kysr/yIiIv8fHx//ICAg/yAgIP8fHx//Ghoa/yIiIv8lJSX/FBMV/25tZ//h4dX/0tHG/9TT + yP/T0sf/0tHF/9HPxv/Qzcb/z8zE/83MwP/Myr//ysi+/8nGuf/Gxb7/xcbD/829lv/Zs2H/4q9D/+Kv + Ov/esk7/yrWD/7Gwq/+sp5//qqOY/6aelP+imI7/opyS/8a4sP/BkYv/smNk/7BUU/+3b3H/xLW2/8/V + zv/EwLX/oJaG/5GFef+TiHz/kYV4/5CDdv+OgnT/jX5x/4yGcf+vXYD/ngBN/8Ete//9dc7//3ra/+E1 + k//t0t///P////j////l2d7/s0N3/4JlXf91ZFH/d2FR/3JeTv9tWUb/blhH/3RhUf93ZVX/b1pK/21X + Rf9sVjr/bFY3/2xWNf9pUzX/Z1BA/2dQRf9mUT//ZlA//2ZPP/9mTz//ZU4+/2RNPf9kTj3/Y00+/2NM + QP9kTT//X0k+/317ev+Ih4n/h4eH/46Ojv95eXn/jIyM/5mZmf+ampr/ioqK/2tra/9VVVX/SkpK/zAw + MP80NDT/aWlp/5ubm//ExMT/ioqK/6urq//Ly8v/tbW1/35+fv9ZWVj/rh5i/6cAS/+mAU//pQBM/6QA + S/+jAEr/ogBI/6EAR/+eAkb/pABF/5EuWv80Pzr/QD4//zExMf8lJSX/IiIi/yQkJP8gICD/ExMT/xYW + Fv8aGhr/Hh4e/yIiIv8hISH/ICAg/yIiIv8eHh7/HR0d/yMjI/8jIyP/HBsa/6Sjmv/X1Mn/y8m+/83L + wP/Nyr//zMnB/8vIwf/Kx8D/yce9/8jGvP/Hxbn/xcO4/8K/s/+/uq7/vLu3/7e6uv+0tbP/srGt/6us + qv+opaP/qKCV/6Wckv+jmpD/o5iO/5qSiP+3ppz/uWhl/5cXGv+dGhP/mQ0L/6skJv/Fh4r/t7XJ/52e + 0f+qpcb/mI19/4t+bv+Mf3H/inxu/4l6bP+IeGv/gnVl/5B4cP+vM3H/rwBb/9QtjP/uWbP/2CyN/8ZN + if/RkKz/u1J//7kgbf+oT3H/bmRL/3JcTf9uW03/dWVU/4R1aP+JenX/jHx7/4V2cv9jTUX/YEo+/2ZQ + QP9oUkP/ZU9C/2VPQv9lTz//ZU4+/2VOP/9kTz7/ZE5B/2VOQv9kTUD/Y01A/2JNP/9iTUD/YkxA/2NO + Qf9gRzv/bWJc/4uNjf+JiYn/j4+P/4iIiP9/f3//nJyc/5ubm/+Wlpb/j4+P/4mJif+Li4v/hISE/3t7 + e/+Li4v/tra2/7m5uf+6urr/w8LD/72+vv+loqP/WGRe/4g8Yf+xAVP/pwFP/6cAT/+mAE3/pQBM/6QA + Sv+iAEn/oQBI/58BRv+jAEX/mx5W/zg9O/8+PT7/NTU1/yYmJv8kJCT/ISEh/yEhIf8iIiL/ICAg/yEh + If8iIiL/FxcX/w8PD/8PDw//ExMT/xsbG/8bGxv/ISEh/yUlJP8cGxv/Pjs5/8jFvP/Kx77/yca9/8nH + vf/Jxr//yMW+/8fEvf/Fwrv/w8C4/768tP+5uK//ubau/7u3sP+0sKX/sKqd/66nm/+qo5b/p5+T/6Wc + kP+jmY//oJaN/5+Vi/+ekYj/mpaL/7uRiv+WERP/pzYU/7VLG/+vMh//pAYM/6A2af9KQN//KSrZ/2Bh + 5f+jmr3/iHlm/4V2av+FdWb/g3Jj/4FwYv+AbGD/emtb/4puZf+wQnX/uA9p/74DZ/+3A2L/sQBZ/68A + V/+6C2j/rkZ1/3NfTv9rVkX/aFJB/5WHfP+KfHf/gHBn/49+Yf+WgU//nYlO/5uHUf+KdlH/aFNK/1xG + O/9lTz3/Y05C/2NOQf9kTkH/ZE5C/2JOQf9iTUD/Yk1B/2NNQv9jTkL/Yk5B/2JOQv9jTkL/Yk5C/2FM + Qf9dS0H/g4OB/46Ojf+OjY7/lJSU/319ff+YmJj/ioqK/4SEhP+jo6P/l5eX/4qKiv+xsbH/tra2/7Oz + s/+vr6//srKy/7q6uv+/v7//tbS1/3d6ef9hVlv/sQ9d/6kAT/+pAVH/qABP/6cATv+lAEz/pABL/6MA + Sv+iAEj/oAFH/6AARf+oE1f/RzxB/zk8O/87Ojr/KCgo/yQkJP8iIiL/ISEh/yAgIP8gICD/IiIi/xMT + E/8CAgL/AwMD/wMDA/8GBgb/CgoK/xISEv8aGhr/IyMj/yYlJv8XFRX/cW9r/9HOx//DwLn/xcK7/8XB + uv/DwLn/wr+3/8C8tf+6t7H/vrSu/8i7tP/Eu7L/u7Ss/7KqoP+vp53/o5uP/52Viv+elYv/nZSK/52S + iP+bkIb/mY6E/5iMg/+UiYD/x7e0/6QpKv+qLRz/qSEZ/6sgJv/RZWP/0k5v/6iV8P9OUfD/ExLX/4qH + 6P+SgXb/fGpc/39sYP99aVz/e2dY/3llWf95Y1j/cmJO/3ZnUf+NXWT/oklv/7E9df+zP3f/qU11/45d + ZP9qW0P/ZlFC/2lSQv9nUT7/aFFF/35rVv+jjDT/rowQ/7CJAP+xiQP/tY4E/7qXDf+6oDz/h3NP/1xI + Q/9jTUD/Yk0+/2NNQv9jTkL/Yk5C/2JOQ/9jTkL/Yk5D/2NOQ/9jT0P/Yk5E/2FNQ/9iTkL/aVJH/2hQ + Q/9yaWf/kJGU/5CPjv+UlZX/jIyM/4mJif+Dg4P/jY2N/6ioqP+ioqL/eXl5/5qamv+xsbH/sLCw/7Oz + s/+3t7f/vb29/7u6uv+PjI3/VmJc/6EqZf+vAFL/qgFT/6kAUf+oAFD/pwBO/6YATf+lAEz/pABK/6IA + Sf+hAEf/nwBH/64FUf9mPlD/Mzs4/0RCQ/8sLCz/IyMj/yIiIv8hISH/ISEh/yMjI/8YGBj/BwcH/w4O + Dv8RERH/Dw8P/wYGBv8HBwf/CAgI/xEREf8eHh7/JCQk/yIjI/8hISD/o6Ca/8fDvP+7uK7/uras/7Wx + qP+wrKH/q6ed/7Sqo/+yv7z/dru+/z+nsv8zq7r/RWpt/2xlXv+amI//pJyS/5eOg/+ZjYP/l4yC/5aL + gf+UiX3/lIh9/4h7bf+5uK3/zpWU/6IcDf+yLx//pgkR/8o5RP/3e4//xLDu/4qO//89POL/TErk/5WD + if90YE3/eGRa/3ZhVf9yX0//cFpI/2xXRf9uWUv/bFdG/2VYQ/9mWUL/aFpE/2ZZQ/9iVj7/YFA7/2ZP + QP9mT0L/ZlA//19JOv92YlL/u6M1/7OFAP+3iAD/uo8e/7qTF/+2jxX/tI0Z/7OHAP/Enw3/iXA8/1tG + QP9jT0L/Yk5D/2NOQ/9jTkP/Y09E/2NORP9jTkT/Y09E/2NORf9hTUT/bFZG/4FnRv+bfzj/tpcl/6+T + KP+Li4n/kpKT/5SUk/+ZmZn/hISE/5CQkP9+fn7/hISE/39/f/+BgYH/qqqq/7Gxsf+ysrL/tbW1/7i5 + uP+0s7T/k5GS/15wZ/+SS27/tQNZ/6oBU/+rAFP/qgBS/6kAUP+oAE//pgBO/6UATP+kAEv/owBK/6EA + R/+hAUn/qQBK/4wyW/8zQTv/SEVH/zIyMv8lJSX/IyMj/yEhIf8gICD/JCQk/xcXF/8JCQn/DQ0N/w4O + Dv8WFhb/GRkZ/woKCv8JCQn/CQkJ/xoaGv8hISH/JiYm/xwcHf9APzz/qaGZ/6GYjv+flov/nZSJ/5uS + h/+ZjoP/qaih/129x/8Aorf/AKjC/wCCmP8AAQP/AAAA/xYKCP9sW1P/npSI/5KHff+Shnv/kYN5/46C + dv+Mf3P/i3xy/4d4aP/RzMb/zoiH/7A+Qf/Mc2j/cj2g/31t5P9qbf3/Pj7x/zEw5f9LRt//fWte/3Bc + Sf9vWU7/bFZH/3BdTv96al3/gXNo/4d5cf9rVUr/ZEw+/2pRQv9oT0H/ZU0//2ZNQP9lTUH/ZE5C/2RO + Qv9lT0H/W0dE/6aTS//FmQH/2qsL/9yyJv/NoyH/wI0A/72MAP+/kQj/vJUj/7+dPv/HrVj/aVRC/19M + Rf9kT0X/Y09E/2FORv9jT0X/Yk9F/2JPR/9jT0f/YU5G/29cRv+WekD/y6QV//LBAP/8vQD//7UA/6eN + WP+Okp7/l5WS/5ubm/+Pj4//jo6O/6CgoP+QkJD/lZWV/6ioqP+wsLD/sbGx/7Kysv+wsLD/r62u/6Cg + oP+Ok5H/p016/7YFW/+tAFX/rQFV/6wAVP+qAFL/qQBR/6gAUP+nAE7/pgBN/6QATP+jAEr/ogBI/6MB + Sv+jAEj/qxdb/0U8QP9CREP/QUBB/yUlJf8gICD/IiIi/yEhIf8gICD/FRUV/x4eHv8nJyf/Kioq/yoq + Kv8xMTH/JSUl/wkJCf8KCgr/Hx8f/x0dHf8kJCT/JyYm/xobGv9hWlT/n5SG/5WLf/+YjYP/lYuA/6KX + jP94eXP/Dw0O/wZmc/8Bu9H/AKfA/wByif8DdYr/BH2N/wBFTv9YUEz/l4V6/4p9cf+KfG//iHpt/4d3 + a/+Fdmj/gG9i/4JxY//NysD/+Pn5//////+6w///LzLp/y4s6v9EQvD/d3by/4l5j/9sVjv/alRH/3Zk + Vv+KfHH/emlg/5WHgf+LeWP/iXlo/31pV/9tWk3/XEhA/19JPf9kT0H/Y01B/2NOQv9jTkL/Y05C/2NP + QP9eS0n/rpI0/9qpAP/+8xT/++kl/+CpAP/OqTn/0LZi/8aeOv/Mrkr/0Lx//9OxTP+DbEb/W0hG/2RR + R/9jT0f/YlBH/2JQR/9hUEn/YlBI/2FPR/9oVUr/j3RD/9eVC///qQD/+p4K//aeK//+iQ3/23YR/42Q + kf+ZmJn/mZmY/56env+FhYX/o6Oj/6qqqv+srKz/rq6u/66urv+srKz/t7e3/87Lzf/Lzsz/tL65/7lU + h/+1AFX/rgFX/68AV/+tAFX/rABU/6sAU/+qAFL/qQBQ/6cAT/+mAE7/pQBM/6QAS/+iAEn/owBK/6IB + S/+vAE//fUBc/zlEP/9LSUr/HBwc/xoaGv8WFhb/HBwc/yMjI/88PDz/Kioq/zAwMP86Ojr/R0dH/0lJ + Sf9WVlb/NDQ0/wICAv8hISH/IiIi/x4eHv8mJib/IyQl/yYmJf+GfXL/mo+D/5WLgf+VioD/n5WL/15U + Tf8HHiH/Apar/wW71f8ZuM7/L9Hq/wimvP82eH7/atfa/xqVo/9zaWL/intt/4R1Z/+CcmT/gG9h/35s + X/9+a17/eGVY/3FcTP+VhXj/yb22//Dn3P/MyuP/vLbh/8e/wf+ainL/aVI6/2lTRP9nUED/bFlK/35t + aP+WfVr/sJ17/6JsG/+yjlD/vaJg/6yBJf+hh1T/blxO/1tFO/9lUET/Yk5D/2NOQv9jTkP/ZFBC/1pI + S/+fgCn/5sM5//v1fP/775D/5bcw/+DIb//bwmv/0aw9/8ugHf/DmA//0aAA/4NsOf9ZSk//Y1FJ/2FP + Sv9iUEr/YlBJ/11PSv9eT0r/YE5J/3RkUv+0fiz//IEA//t4Af/2gR3/9LGF//WWUv/6WwD/p3xi/5Sd + pP+bmZf/oKCg/5KSkv+QkJD/qqqq/6mpqf+pqan/sbKy/9fW1v/y7/H/2OHc/7WytP+3P3z/swBV/7AD + W/+wAVn/rwBX/64AVv+tAFX/qwBU/6oAUv+pAFH/qABP/6cATv+mAEz/pABL/6IASf+kAEr/pQFM/6YA + Sv+rHGD/TU1N/0BBQP8oJyj/Hh4e/xgYGP8YGBj/Hx8f/zExMf8tLS3/Nzc3/0NDQ/9TU1P/X19f/2Zm + Zv9jY2P/BAQE/yMjI/8lJSX/Hx8f/yIiIv8oJyf/Hx8f/0JAO/+aj4L/lYp//5OIf/+Zj4P/eGdd/w2i + tf8MgZD/Fpmo/2jQ3v+Bzdj/Ssnc/wZnfv9bra3/M/3//05kY/+KcWD/fWxg/31qXf96Zlr/d2RX/3Fe + T/9xXk7/b1xP/2xYSP9xXlP/cFtO/3diTP94Ykn/Yks4/15GOP9mUEL/ZU9C/2ZQQv9bQzD/rqKW/8q2 + m/+1gDz/0Kdz/9m1df/HmlX/tHoS/7V4Bv/An1X/emxm/1tGOv9kUEb/Y09E/2NORf9jT0X/XkxH/2tX + Qf/XvWD/6MNV/+C5Qf/ZrzL/0Z8Q/8uWAP/MmQD/y54Q/9mrEP/KoBH/ZFRN/11NS/9gUEv/YE9M/2FQ + TP9kUk7/Z1RQ/2dVUf9iUE3/cGNJ/8BzHf/8YQL/9l8C//liBv/6oWT/+4Ux//9kAP/QaBf/kZSW/56d + nf+enZ3/oaGh/4eHh/+mpqb/o6Oj/76+vv/y7vD/8fPy/8PRyv+vjJ//uCJu/7UAWP+zAl3/sgBb/7EA + Wf+wAFj/rgBX/60AVf+sAFT/qwBT/6oAUf+oAFD/pwBO/6YATf+lAEz/owBK/6QAS/+lAEz/pAFN/7AA + Uf+DNlv/RVFL/0VCRP8XFxf/HBwc/xUVFf8eHh7/HR0d/yIiIv83Nzf/SEhI/1hYWP9lZWX/YGBg/0hI + SP8bGxv/JSUl/yQkJP8lJSX/Hh4e/yUlJP8pJyf/Hh4f/2phWv+dj4P/kIZ7/5KIe/+VfnP/SrjA/wZF + Tv8AYW//N9/0/1zb7P8o1+3/Ds3j/xassf8UT1D/W09K/4JtXv90YFT/cVxP/3JeT/9yX1H/fGte/3hm + XP96aVz/kIJ4/42AeP9vXE//Yks//2NNQP9mUUH/ZlBD/2NNQf9kT0L/XUlB/3heR//MsW//wJZm/9ii + Tf/0xUX/+uST//Xadv/duF3/u3kA/7t7Dv/Lvar/ZlVP/2BMQv9jUEb/Yk9G/2FPSP9iUEf/WUpJ/3pj + QP/Nogj/4aoA/+GxC//eqgr/37Iq/96tB//ltQb/1KUM/3llPv9aSk//ZVRN/2dUUf9mVFH/YFFO/1ZJ + Rf9GPDr/NC4t/x0bHf8fHQr/j1UA//1MAP/6TgD/8GkA/9loEf/AcDD/qn1U/52Hcv+YlpT/np2e/6Ce + nv+jpKT/kZGR/5CPkP/Jxsj/8/Tz/9Ph2v+xp63/tFaG/7sGZP+2AFz/tQJg/7QAXf+yAFv/sQBa/7AA + Wf+vAFf/rgBW/6wAVf+rAFP/qgBS/6kAUP+oAE//pgBO/6UATP+jAEr/pABM/6YATf+nAU//pgBM/7ET + X/9ZT1T/TlFQ/0VERP8fHx//HR0d/yQkJP8jIyP/Hx8f/yEhIf8wMDD/Pj4+/zo6Ov8fHx//ICAg/yQk + JP8lJSX/JiYm/yYmJv8kJCT/ICAg/ygnJ/8kJCP/LCoo/4l8dP+Vh3r/j4J3/49+cv+OhHr/UaWs/yKi + tP8al6T/EGpy/wg6P/8GEA//AwAA/zIkI/94al//dWJT/3tqXv+IeXD/iHpv/4JzaP+UhXr/jHlo/415 + af93Zln/YEc2/15GOP9mT0T/Zk9E/2ROQv9kT0P/Y05D/2VQRP9bRTn/hXVp/8GLMv/KnVD/57hd//7u + cP/9/mv///al/+nDXf/RngL/v4AA/9apYP+SiIb/V0M6/2RSSv9iUEj/YU9J/2FPS/9jUEr/WkpM/2RW + Tf+ZfzX/wJkY/9CmDf/VqBP/yaAb/6aIMf9vXVP/X09S/2BRTP9SR0X/QTk5/zAqKf8cGhj/CgsK/wAA + AP8AAAD/AAAA/wQEBP9OPxn/rGM2/6NuVf+QhHb/io6O/4uVnf+RmaH/mJyi/5ucm/+enJz/n52e/6el + pv+TkZL/naCf/9ro4f+2s7X/smiP/7wYbv+6AF3/twBh/7cCYf+1AF7/tABd/7MAXP+yAFv/sQBZ/68A + WP+uAFb/rQBV/6wAVP+qAFL/qQBR/6gAUP+nAE7/pgBN/6MASv+lAEz/pgBN/6cAT/+nAVD/rgBQ/5wv + ZP9FUUv/XVpc/zg4OP8jIyP/IiIi/yIiIv8jIyP/IiIi/x8fH/8eHh7/Hh4e/yMjI/8oKCj/JSUl/yIi + Iv8lJSX/JiYm/ygoKP8hISH/IiIi/yopKP8eHiD/SkM//5WFeP+LfXL/inxv/4l3Z/+Oc2L/dmVa/087 + NP81Ih7/Lh4b/zUrKf9TTEr/eWtg/3FbS/+Ec2n/oZWO/4JzZv90YVP/o5KB/5+Yk/+Ei53/k5Wf/8TA + uP+8uLT/jX92/2BKPv9iTEH/ZVBF/2NPRP9kT0T/ZVBF/2FLP/9uYFv/1b+c/9CcS//fsVD/8tSG//nb + MP/3yyf/5LUb/9ysAP/Wqhn/4rxl/6OWkP9VQz7/YlJM/2FQS/9gUEz/YFBM/19PS/9gUEr/X05L/1hK + UP9eT1b/ZldR/2ZXU/9YTFD/RT1H/zk1Nv8sKCX/GBUW/wcHB/8AAAD/AAAA/wAAAP8JCQn/ISAg/z09 + Pf9bW1v/dXZ2/4SEif+DjpP/h5GV/4+Qlv+VkpT/lpSS/5iWlP+bmJn/n5ye/6Ogof+jpaT/mqSe/4KM + h/+xpaz/t12O/7sccv++AGL/uwBj/7kCZf+4AGL/twBg/7YAX/+0AF7/swBd/7IAW/+xAFr/sABY/68A + V/+tAFX/rABU/6sAU/+qAFH/qABQ/6cATv+mAE3/pABL/6UATP+mAE7/qABP/6kAUf+oAVD/tgRa/3pF + X/9LVVD/VlNU/yoqKv8iIiL/IyMj/yQkJP8iIiL/IyMj/yUlJf8ZGRn/ExMT/xAQEP8qKir/MzMz/yoq + Kv8nJyf/Jycn/ycnJ/8gICD/JyYm/ycnJ/8gISL/al5V/49/bv+HdWb/hXVn/4FxY/+Db2D/gnNj/4Bw + Yv9+bF//fWpd/3plWf9xXFD/b1tN/3FcTP9wWk3/YEg4/7Ommf9xltf/FlfV/wRV6v8LWuv/o7nV//j3 + 9P/n6uv/ubKr/2ZTR/9iTkT/ZVFH/2VRRv9lUUf/ZVNK/1hEOv+jmZf/58R8/9ahLv/XoRT/26MK/96z + Jv/hw1n/v7ed/+Ti1v//////fm9p/1hIRP9iUU3/X09K/2BRTP9kVFD/ZFRR/2VVUf9jU1D/XE9K/01D + P/85MzD/JiIh/xMTEv8FBwP/AAAA/wAAAP8AAAD/DQ0N/yQkJP8/Pz//XFtb/3Rycv+CgYH/iYmJ/4qK + iv+IiIj/iIiH/4yJiP+Pi4v/k4+R/5mUlf+bmZn/mJqZ/5Sdl/+Nm5P/iJKM/4iDhv+PZX3/tzx//8QV + dP/AAGT/vgBm/7wCaP+7AWb/ugBk/7kAYv+4AGH/tgBg/7UAXv+0AF3/swBc/7EAWv+wAFn/rwBX/64A + Vv+sAFX/qwBT/6oAUv+pAFD/pwBP/6YATf+kAEv/pgBN/6cATv+oAFD/qQBR/6sBU/+rAFH/tBFh/11P + Vv9XXFn/SUdI/yUlJf8kJCT/IyMj/ykpKf80NDT/JiYm/xgYGP8DAwP/DQ0N/xEREf85OTn/Nzc3/zAw + MP8rKyv/LCws/ycnJ/8gICD/KSgn/yQlJf8wLSz/f29i/4ZyZv+BbmH/f2tf/3xnW/95ZFj/d2NV/3Vh + Uv90X0//cFxQ/3BcUP9vWk7/b1pM/2lTRv9/alv/09PR/xBm4f8AX/P/BG32/wBz//9Dr////f76//j5 + +//09/r/ua+p/2BLQv9nVEv/ZVJJ/2RSSv9kUkn/ZVNJ/1tJQv+fkYX/48N3//rkpv/c3Nr/ssb//9Xk + //+4z///4er//6ibkf9XRUH/ZFRS/2FTUP9nVlH/X0xK/1JCQP9JPjz/NjAu/yEfHv8QEA//AgIC/wAA + AP8AAAD/AgIC/xISEv8oKCj/REJB/1xaWv9tbW3/eXl5/35+fv+Afn7/f319/317e/9+fX3/g4GC/4mF + h/+Oioz/j4+P/4qRjf+Fkov/gY+H/4CDgP+Ff4L/kGN9/6FQff+uKnT/vQ9w/8gBcf/EAGr/vwBp/78D + a/++AWn/vQBn/7wAZv+6AGT/uQBj/7gAYv+3AGD/tgBf/7QAXf+zAFz/sgBb/7EAWf+vAFj/rgBW/60A + Vf+sAFT/qgBS/6kAUf+oAE//pwBO/6UATP+mAE3/pwBP/6gAUP+qAFH/qwBT/6sCVf+wAFP/qTBs/1FZ + Vf9eXV7/PDw8/yUlJf8hISH/SEhI/1BQUP8qKir/Hx8f/y0tLf84ODj/IyMj/xISEv8zMzP/Li4u/ygo + KP8dHR3/KCgo/yUlJf8iIiP/KSkp/yAiI/9LQT7/hXBj/31oXP98Z1v/e2Za/3lkWP93Ylb/dGBU/3Jf + Uf9xXVH/cV1R/3BcUP9xXFH/aldL/4NtX//Gzdf/C3bs/xZ/8v8Bfff/DYj+/3DF///9//z////8//// + +P/08e7/gHBr/2FPRv9oVk3/ZlRO/2ZTTv9mU03/ZVRL/1lIQv91aHD/rKSq/8vJ0P+6wNz/p63T/6Ge + rf+Gd2r/WUlF/1pSTP9UST7/U0Y3/ywoKv8vRjz/ME9D/wAFAf8AAAD/AAAA/wUFBf8WFRb/LCsr/0RE + RP9YV1f/aWdn/3JwcP92c3P/dXJy/3Rycv90cnL/dnR1/3t3ef+BfH7/g4CB/4GDgv98hH//eIZ9/3aB + ev93eHf/g2l5/5NReP+nOnn/uBx3/8kWfv/OAXj/zgB0/8sAcf/GAHD/wgBu/8ECbv/BAWz/wABq/78A + af+9AGj/vABm/7sAZf+6AGP/uABi/7cAYf+2AF//tQBe/7MAXf+yAFv/sQBa/7AAWP+vAFf/rQBV/6wA + VP+rAFP/qgBR/6gAUP+nAE7/pQBM/6YATf+nAE//qQBQ/6oAUv+rAFP/rQBV/6wCVf+3AFj/mDlp/1Bd + Vv9iX2H/MzQ0/ykpKf9TU1P/SUlJ/0FBQf8rKyv/LS0t/ywsLP8+Pj7/Hx8f/xMTE/8QEBD/Dw8P/w8P + D/8QEBD/KSkp/yIiIv8nJib/Kigo/yUjJP9lVkz/gWtb/3llV/95ZFj/eGNX/3ZhVv91YVX/dWFV/3Rg + VP9zYFT/c19U/3JfVP9yX1X/bVhN/8C7uP+s0O//rc/o/wuP9/+av9v//fby//j39v/h6vb/nr3o/+/w + 9f+ej4j/Xk1G/2xaU/9oV1D/ZlVQ/2VUT/9mVFD/aFhS/15PRv9ZRkP/YU5J/2BTRv9WSzv/Sj1B/zUw + P/9KNi//ZTpE/yIlOP8kGxr/Fxkb/xQpH/8hRDb/GiAb/zAtLv9EQ0P/VlRU/2JhYf9oaGj/aWlp/2ho + aP9oZ2j/amhp/25rbP90b3H/eHN1/3l2dv91eHX/bnt0/2p5cP9sdG//c25x/4Znef+cRXn/sSl6/8Qd + gP/SCID/1QB9/9MAev/PAHf/ygB0/8cAc//GAXP/xQJy/8UBcf/EAG//wwBu/8EAbP/AAGv/vwBp/74A + aP+8AGf/uwBl/7oAZP+5AGL/uABh/7YAYP+1AF7/tABd/7MAW/+xAFr/sABZ/68AV/+uAFb/rABU/6sA + U/+qAFH/qQBQ/6cAT/+lAEz/pwBO/6gAT/+pAFH/qgBS/6wAU/+tAFX/rgBX/60BVv+6BF7/hUdn/1Nj + W/9gXF7/Ojs7/0xMTP9CQkL/LS0t/yEhIf8iIiL/Kysr/zMzM/9mZmb/ICAg/x0dHf8vLy//QkJC/xgY + GP8SEhL/Kioq/yEgIf8qKCn/IyUk/zMvLf94Y1j/emVZ/3lkWf95ZVn/d2NY/3hjWf93Y1j/dmNY/3Zi + WP92Ylj/dWJY/3ZjWf9vXVT/gW9k//Dj0///+/X/X7zv/0Wv4v+qxdD/bqPj/8Tb7v+Av/j/mMru/411 + a/9iVFH/a1tW/2pZVf9qWlX/bVxX/2paVv9dTEr/X1BO/19SQ/9AODf/b0Fo/1Q2Sv8SFWb/HCCc/yEY + LP9ONkr/HRxE/ysqLP9AQD7/Pzw9/01IS/9dWlv/YV9f/2BgYP9gX1//X19f/2JhYf9mY2X/amZo/2xp + a/9qbWv/Zm9q/2JxZ/9hbmb/aGxp/3dfbf+MUHX/pDx8/74ggP/QFYf/2wmJ/9wAg//YAID/0wB9/84A + ev/MAXr/ywJ5/8sBeP/KAXf/yQB1/8gAdP/HAHL/xgBx/8QAcP/DAG7/wgBt/8EAa/+/AGr/vgBo/70A + Z/+8AGb/ugBl/7kAY/+4AGH/twBg/7YAXv+0AF3/swBc/7IAWv+xAFn/rwBY/64AVv+tAFX/qwBT/6oA + Uv+pAFD/qABP/6YATf+nAE7/qABP/6oAUf+rAFL/rABU/60AVf+uAFf/sAFZ/68AVv+9D2b/dE5i/1Zg + W/9lYWP/RUVF/zAwMP8SEhL/EBAQ/yAgIP8rKyv/R0dH/1RUVP8mJib/Kioq/zMzM/9UVFT/RkZG/x0d + Hf8oKCj/JSUl/yQkJP8qKSn/ISMk/0xDPf9/a17/eWZb/3pmXP96Zlz/emVc/3llXP94Zlz/eGVc/3hl + Xf92ZVz/dmRc/3dmX/9uXVj/fnFn/8G9wv/U5dH/n9r8/9Lx6P+T0+b/r+X//+bz8f+Hj47/bVlT/3Vj + Yf9zY13/cGBb/2ZZVv9USkf/TkdG/2xrbf89Nyf/f2YA/0k4AP9RGVP/bj9k/xcXJ/8qKEr/MTE2/0BD + P/9MTUX/UlJR/1RUVP9YWFf/WFhX/1hXWP9bWVr/X1xe/2JeYf9iYmL/X2Rh/1tlXv9ZaF3/WmZe/2hc + Y/98Vm3/lkN4/7QqgP/NH4v/3A6O/+IAjP/hAIn/3ACF/9cAgv/TAID/0QGA/9ECf//QAX7/zwF8/84A + e//NAHr/zAB4/8sAd//KAHX/yAB0/8cAc//GAHH/xQBw/8QAb//DAG3/wQBs/8AAav+/AGn/vQBo/7wA + Zv+7AGX/ugBj/7gAYv+3AGD/tgBf/7UAXv+zAFz/sgBb/7EAWf+wAFj/rgBX/60AVf+sAFT/qgBS/6kA + Uf+oAE//pgBN/6cATv+oAFD/qgBR/6sAU/+sAFT/rQBW/68AV/+wAFj/sQFb/7IAWf+6DGT/bU1e/1lm + X/9jXmH/LCws/zMzM/9BQUH/Nzc3/zAwMP9SUlL/RUVF/ykpKf8sLCz/NDQ0/z4+Pv9ubm7/Hx8f/x0d + Hf8sLCz/IiIi/ycnJ/8pKSn/JyYm/2laUf+AbGH/e2de/31pX/97aGD/emhf/3loX/95aF//eGhg/3do + YP93aF//d2df/3dpY/9yYlz/bl5X/4l9dv+lopr/sLWx/8W/uv+zqaX/i3d0/3BcWf9oXlz/Wk9O/0ZA + P/8vLi7/Hh4f/woLC/8UFRX/iYmL/zIxL/83LRH/QTol/ywuLv89Pzz/SkpH/09PR/9TUlD/UlBQ/1FP + Uf9SUVL/VVNV/1hUV/9aV1n/WVpZ/1VbV/9RXlX/UWFW/1pcWv9qWGP/iFJ0/6c+gP/DK4v/2hKR/+UF + k//pAJL/5gCO/+AAiv/aAIf/1wCH/9YBhv/WAYX/1gGE/9UAgv/UAIH/0gCA/9EAfv/QAH3/zwB8/84A + ev/MAHn/ywB3/8oAdv/JAHX/yABz/8YAcv/FAHD/xABv/8MAbv/CAGz/wABr/78Aaf++AGj/vQBn/7sA + Zf+6AGT/uQBi/7cAYf+2AGD/tQBe/7QAXf+yAFv/sQBa/7AAWP+vAFf/rQBV/6wAVP+rAFP/qgBR/6gA + UP+mAE3/pwBP/6kAUP+qAFL/qwBT/6wAVf+uAFb/rwBX/7AAWf+xAFr/sgJc/7QAW/+9F2z/b0pd/1Ng + Wf9APD7/MDAw/0xMTP8+Pj7/MzMz/19fX/85OTn/MzMz/y4uLv8mJib/OTk5/y0tLf8QEBD/FhYW/yws + LP8nJyf/IiIi/yoqKv8lJSb/ODQz/31qYf9+amL/fWpi/31rYv97a2L/emtj/3pqY/95amX/eWll/3lp + ZP94aWP/eGhj/3tqZ/98bWj/eGdj/3RiXv9wXlz/Y1ZR/1BGRf9CPj3/NDIz/yAgIP8RFBP/CwwN/woK + C/8ODg//Gxka/yYlJf8sLCz/Pj4//0FDSf9HSE3/T05N/01MS/9MTE3/TkxP/1BNUP9STlH/UVFR/05R + T/9JVE3/R1hN/0tYUP9bVVn/c1Ro/5NGeP+3MYj/1BuT/+UOmf/uBJv/7gCX/+kAk//jAJD/3gCN/9wB + jP/cAoz/3AGL/9sBiv/aAIj/2QCH/9gAhf/XAIT/1QCD/9QAgv/TAID/0gB//9EAff/PAHz/zgB7/80A + ef/MAHj/ygB2/8kAdf/IAHT/xwBy/8UAcf/EAG//wwBu/8IAbf/AAGv/vwBq/74AaP+9AGf/uwBm/7oA + ZP+5AGP/uABh/7YAYP+1AF//tABd/7MAW/+xAFr/sABZ/68AV/+uAFb/rABU/6sAU/+qAFH/qQBQ/6YA + Tf+oAE//qQBQ/6oAUv+rAFP/rQBV/64AVv+vAFf/sQBZ/7IAW/+zAFz/tAFe/7UAW/++Dmn/f1Fq/0VS + S/8mJCX/IiEi/yIiIv8rKyv/Ojo6/ygoKP81NTX/R0dH/zs7O/8ICAj/FRUV/wsLC/8dHR3/Kysr/yoq + Kv8kJCT/JSUl/ywsLP8kJCT/U0pG/4NxaP98a2X/fm1n/3xsZf97a2b/e2pm/3trZv99bWf/gG9r/4Bw + bP9/b2z/empo/21hXv9cVVT/SkZF/zY0NP8jJSX/Fxka/xIREf8QDw//FRQV/x8fH/8rKyv/ODc3/0FB + Qf9IR0f/TUpK/0xLS/9JSUn/SklI/0xJSv9NS0v/TkxM/0tLS/9FTEj/QU9G/0JTSP9MUk7/YFdd/4FS + cv+nQ4T/xiiP/+EUm//wC6L/9QCg//IAnP/rAJj/5gCV/+IAk//hAZL/4QKS/+EBkf/gAJD/3wCO/94A + jf/dAIz/3ACK/9sAif/ZAIj/2ACG/9cAhf/WAIP/1QCC/9MAgf/SAH//0QB+/9AAff/PAHv/zQB6/8wA + eP/LAHf/ygB1/8gAdP/HAHP/xgBx/8UAcP/DAG//wgBt/8EAbP/AAGr/vgBp/70AZ/+8AGb/uwBk/7kA + Y/+4AGL/twBg/7UAX/+0AF3/swBc/7IAWv+wAFn/rwBY/64AVv+tAFX/qwBT/6oAUv+pAFD/pwBO/6gA + T/+pAFH/qgBS/6wAU/+tAFX/rgBW/68AWP+xAFn/sgBb/7MAXP+1AF7/tQFg/7YAXv/CB2j/lUpy/0VS + S/8tMS7/KSYo/yEhIf8fHx//Pz8//zg4OP9NTU3/ZWVl/ywsLP8NDQ3/ERER/ycnJ/8qKir/KSkp/yoq + Kv8iIiL/KSkp/yoqKv8sKSr/cGJb/4Bwa/99bWr/gXJt/4Fybf+Ccm7/gXFt/3lsaf9tYl7/XFRQ/0VD + Qf8zMjH/IiMk/xcZGv8UFBT/FBQU/xgaGv8jIyP/Li4u/zk5Of9CQUH/RkZG/0dHR/9GRkf/RkVG/0ZF + Rv9JRkj/SkZJ/0lGSP9ER0b/P0tB/ztEQv8/R0f/UVBO/21PY/+RQ3f/tziM/9Ydmf/uF6b/+Qao//oA + pP/1AKD/7gCc/+oAmf/nAJj/5wKY/+cBl//mAZb/5QCV/+QAlP/jAJP/4gCR/+EAkP/gAI//3wCN/94A + jP/cAIv/2wCJ/9oAiP/ZAIf/2ACF/9YAhP/VAIP/1ACB/9MAgP/RAH7/0AB9/88AfP/OAHr/zAB5/8sA + d//KAHb/yQB1/8cAc//GAHL/xQBw/8QAb//CAG3/wQBs/8AAa/+/AGn/vQBo/7wAZv+7AGX/uQBj/7gA + Yv+3AGD/tgBf/7QAXv+zAFz/sgBb/7EAWf+vAFj/rgBW/60AVf+sAFT/qgBS/6kAUP+nAE7/qABP/6kA + Uf+rAFL/rABU/60AVf+uAFf/sABY/7EAWv+yAFv/swBd/7UAXv+2AF//twFh/7YAYP/DAmj/ry9z/2VU + Xf82RD3/Kioq/xoYGf80NDT/KCgo/yUlJf9ZWVn/S0tL/wYGBv8nJyf/Kysr/ykpKf8qKir/Kysr/ygo + KP8iIiL/LS0s/yYnKP8/Ojn/g3Js/3xuaf9wY17/a2Fe/1hSUP9EQT//MzEx/yMkI/8aHBv/FxcX/xgY + GP8dHR3/JyYm/zEwMP87OTn/QEBA/0NDQ/9ERET/Q0ND/0RDQ/9FQ0X/R0NF/0ZDRf9ERET/P0RA/zlH + Pv85Sj//Qk5G/1tRVf96PW//o3R//8tTi//lGKr/+Q+p//4BrP/8AKj/9gCk//EAoP/tAJ7/7AGe/+wB + nv/sAZ3/6wGc/+sAm//qAJr/6ACZ/+cAl//mAJb/5QCV/+QAk//jAJL/4gCR/+AAj//fAI7/3gCN/90A + i//cAIr/2gCI/9kAh//YAIb/1wCE/9YAg//UAIL/0wCA/9IAf//QAH3/zwB8/84Ae//NAHn/zAB4/8oA + dv/JAHX/yABz/8cAcv/FAHH/xABv/8MAbv/BAGz/wABr/78Aaf++AGj/vABn/7sAZf+6AGT/uQBi/7cA + Yf+2AF//tQBe/7MAXP+yAFv/sQBZ/68AWP+uAFb/rQBV/6wAVP+qAFL/qQBR/6cATv+oAFD/qQBR/6sA + Uv+sAFT/rQBW/68AV/+wAFj/sQBa/7MAW/+0AF3/tQBe/7YAYP+4AGH/uQBj/7gAY/+/AGP/wxh0/5BQ + c/9PUlD/OUE8/zEuMP8rKSv/KSkp/zAwMP8oKCj/Kioq/ywsLP8qKir/Kioq/ysrK/8rKyv/Kysr/yUl + Jf8nJyf/LS0t/yoqK/9CPjz/ZGFg/2RlZP8fICH/Gxsd/xgZGf8bGxv/ISEh/yUkJf8vLy//ODg4/z09 + Pf9AQED/QEFB/0FAQf9BQEH/Q0BC/0RAQ/9CQEL/PkA//zhCPP81RTv/Okg//0hKSf9kTVz/i0Vz/7M9 + jf/WK5v/8RGu//8vsv//my7//5Qh//kiov/xAKj/8AKg//ABo//xAaL/8QGi//AAof/wAKD/7gCf/+4A + nv/tAJ3/6wCc/+oAm//pAJn/6ACY/+cAl//mAJb/5ACU/+MAk//iAJH/4QCQ/+AAj//fAI3/3QCM/9wA + i//bAIn/2QCI/9gAhv/XAIX/1gCE/9UAgv/TAIH/0gB//9EAfv/QAHz/zgB7/80Aev/MAHj/ywB2/8kA + df/IAHT/xwBy/8YAcf/EAG//wwBu/8IAbP/AAGv/vwBq/74AaP+9AGf/uwBl/7oAZP+5AGP/twBh/7YA + X/+1AF7/swBd/7IAW/+xAFr/sABY/68AV/+tAFX/rABU/6sAUv+pAFH/pwBP/6gAUP+qAFH/qwBT/6wA + VP+tAFb/rwBX/7AAWf+xAFr/swBc/7QAXf+1AF//twBg/7gAYf+5AGP/uwBk/7oBZv+8AGT/xwBr/7Yj + dP98VWr/SVNN/z5FQP88Ojv/NTEz/y8uL/8sLCz/Kysr/ysrK/8rKyv/Kysr/ywsLP8sLCz/LS0t/yUl + Jf8rKyv/Li4u/yUmJv8nJyf/S0tL/x0cHP8lJSX/Kioq/y8vL/8yMjL/SUlJ/0JCQv88Ozv/Pz0+/0E9 + P/9APT//Pj0+/zg+Ov8zPjf/M0Q5/z1GQP9STVD/dERk/5o9e//DK5D/4hqg//YVrf//Aa3//wCp//oA + q//3Jaf//Jso//yVAP/9lgD//poh//cpo//0AKr/9AOj//MApf/yAKP/8QCi//AAof/vAKD/7gCf/+0A + nv/sAJz/6wCb/+oAmv/pAJn/5wCX/+YAlv/lAJX/5ACT/+MAkv/hAJH/4ACP/98Ajv/eAIz/3ACL/9sA + if/aAIj/2QCH/9gAhf/WAIT/1QCC/9QAgf/SAID/0QB+/9AAff/PAHv/zQB6/8wAeP/LAHf/ygB1/8gA + dP/HAHP/xgBx/8QAcP/DAG7/wgBt/8EAa/+/AGr/vgBo/70AZ/+7AGX/ugBk/7kAY/+4AGH/tgBg/7UA + Xv+0AF3/sgBb/7EAWv+wAFj/rwBX/60AVf+sAFT/qwBS/6kAUf+nAE7/qABQ/6oAUf+rAFP/rABU/64A + Vv+vAFf/sABZ/7EAWv+zAFz/tABd/7UAX/+3AGD/uABh/7kAY/+6AGT/vABm/70BaP+8AGj/wgBo/8sK + df+wK3T/fk9o/05TT/87Rj//Njk2/zMxMv8xLjD/Lywu/ywqK/8nJib/JCQk/yQkJP8oKCj/Kysr/ykp + Kf8xMTH/MTAw/ysrK/8qKir/Nzc3/0VFRf9WVlb/a2pr/3d0dv93c3b/aWdo/zM1NP8yOjX/Lz40/zRE + Of9CQ0L/X0ZW/4NKb/+rOYT/zyGU/+oYo//5B6n//gCp//sApv/2AKT/8gCj//EDov/yAKj/9iyo//6d + Kv//lgD//5MD//+TA///lgD//psl//cqpf/0AKv/9AOj//MApf/yAKP/8QCi//AAof/vAKD/7gCe/+0A + nf/sAJz/6gCb/+kAmf/oAJj/5wCX/+UAlf/kAJT/4wCS/+IAkf/hAI//3wCO/94AjP/dAIv/2wCK/9oA + iP/ZAIf/2ACG/9YAhP/VAIP/1ACB/9MAgP/RAH7/0AB9/88Ae//NAHr/zAB4/8sAd//KAHb/yQB0/8cA + c//GAHH/xQBw/8MAb//CAG3/wQBs/8AAav++AGj/vQBn/7wAZv+6AGT/uQBj/7gAYf+2AGD/tQBe/7QA + Xf+zAFv/sQBa/7AAWP+vAFf/rgBW/6wAVP+rAFP/qgBR/6cATv+oAFD/qgBS/6sAU/+sAFX/rgBW/68A + V/+wAFn/sgBa/7MAXP+0AF3/tgBf/7cAYP+4AGH/uQBj/7sAZf+8AGb/vQBo/78Aaf+/AWv/vwBq/8YA + bP/OCXf/vSN6/5BKcv9hS1f/P0hD/y07M/8oNC3/LjQw/z4/P/9MSkv/SkZJ/zw4Ov8tKiz/Hxwe/yMg + Iv8zMDL/MzAy/0E+QP9zb3L/ZmNl/11cXf9SVlT/P0tD/y9ANf82Pzr/S0RJ/2xGX/+VQ3j/uDCI/9kb + l//uDaD/+AWl//gAo//0AKH/8ACe/+0Anv/uAaD/8AGi//IBpP/0BKP/9ACq//crqf/+nCr//5YA//+S + A///lAD//5QA//+SA///lgD//psl//cqpf/0AKv/9AOj//MApf/yAKP/8QCi/+8Aof/uAJ//7QCe/+wA + nP/rAJv/6gCa/+gAmP/nAJf/5gCW/+QAlP/jAJP/4gCR/+EAkP/gAI//3gCN/90AjP/cAIr/2wCJ/9kA + h//YAIb/1wCE/9UAg//UAIL/0wCA/9IAf//QAH3/zwB8/84Aev/NAHn/ywB3/8oAdv/JAHT/xwBz/8YA + cv/EAHD/wwBv/8IAbf/BAGz/wABq/74Aaf+9AGf/vABm/7oAZP+5AGP/uABi/7cAYP+1AF7/tABd/7MA + XP+xAFr/sABZ/68AV/+uAFb/rABU/6sAU/+qAFH/pwBP/6kAUP+qAFL/qwBT/6wAVf+uAFb/rwBX/7AA + Wf+yAFr/swBc/7QAXf+2AF//twBg/7gAYv+5AGP/uwBl/7wAZv+9AGj/vwBp/8AAav/BAGz/wgFu/8EA + bf/HAG//0AB2/84PfP+8KH3/pEZ9/5FOdf+Hanv/l5SV/6evqv+zw7n/tcS6/6SxqP+Fkor/R1VM/yUy + Kv8iMCf/IzAo/y49M/8pOS//OD06/1FDTP92PmL/oDd5/8gmjv/gFpj/7wuf//MAnv/xAJz/7QCa/+kA + mf/pAJn/6gGc/+wBnv/vAaD/8ACh//IAov/yAKT/9AOj//QAqv/3Kqf//5wq//+WAP//kgP//5QA//+U + AP//lAD//5QA//+SA///lgD//psl//gqpf/0AKv/9AOj//IApP/xAKP/8ACh/+8AoP/uAJ7/7QCd/+sA + nP/qAJr/6QCZ/+gAl//mAJb/5QCU/+QAk//iAJL/4QCQ/+AAj//fAI3/3QCM/9wAiv/bAIn/2QCI/9gA + hv/XAIX/1gCD/9QAgv/TAID/0gB//9EAff/PAHz/zgB6/80Aef/LAHj/ygB2/8kAdf/HAHP/xgBy/8UA + cP/EAG//wgBt/8EAbP/AAGr/vwBp/70AZ/+8AGb/uwBl/7kAY/+4AGL/twBg/7YAX/+0AF3/swBc/7IA + Wv+wAFn/rwBX/64AVv+sAFX/qwBT/6oAUv+nAE//qQBQ/6oAUv+rAFP/rQBV/64AVv+vAFj/sQBZ/7IA + W/+zAFz/tABd/7YAX/+3AGD/uABi/7oAY/+7AGX/vABm/70AaP+/AGn/wABr/8EAbP/DAG7/xABv/8UB + cf/EAHH/xgBx/8wAdP/SAHn/1QB8/9EJf//GEnz/uiR9/7FAhP+vRIT/smGS/7Rymv+vbZb/k1B5/3w4 + Yv94Nl//iTNp/7I4hf/RJZH/5hia/+4Gmv/tAJb/6QCU/+UAk//jAJP/5ACV/+YBl//oAZn/6gGb/+wA + nP/tAJ7/7gCf//AAoP/xAKL/8gCk//MDov/0AKr/9yql//6bJv//lgD//5ID//+UAP//lAD//5QA//+U + AP//lAD//5QA//+SA///lgD//psl//cqpf/0AKr/8wOi//IAo//xAKL/7wCg/+4An//tAJ3/7ACc/+oA + m//pAJn/6ACY/+cAlv/lAJX/5ACT/+MAkv/hAJD/4ACP/98Ajv/eAIz/3ACL/9sAif/aAIj/2ACG/9cA + hf/WAIT/1QCC/9MAgP/SAH//0QB+/88AfP/OAHv/zQB5/8wAeP/KAHb/yQB1/8gAc//GAHL/xQBw/8QA + b//CAG3/wQBs/8AAav+/AGn/vQBn/7wAZv+7AGX/uQBj/7gAYv+3AGD/tQBf/7QAXf+zAFz/sgBa/7AA + Wf+vAFj/rgBW/60AVP+rAFP/qgBS/6gAT/+pAFD/qgBS/6sAU/+tAFX/rgBW/68AWP+xAFn/sgBb/7MA + XP+0AF7/tgBf/7cAYP+4AGL/ugBj/7sAZf+8AGb/vQBo/78Aaf/AAGv/wQBs/8MAbv/EAG//xQBx/8cA + cv/IAXT/yAJ1/8kBdv/KAHf/zAB4/9AAev/UAH3/2AB+/9gAf//YAID/2ACA/9oAg//gAIn/5QCP/+cB + kP/oAJH/5gCO/+EAjP/eAIv/3gCN/98BkP/iAZL/5AGU/+YAlf/nAJf/6ACY/+kAmv/rAJv/7ACd/+0A + nv/vAJ//8ACh//EAov/yA6H/8wCp//cqpP/+myX//5YA//+SA///lAD//5QA//+UAP//lAD//5QA//+U + AP//lAD//5QA//+SA///lgD//psl//crpP/zAKn/8gOh//EAov/wAKH/7gCf/+0Anv/sAJz/6wCb/+kA + mf/oAJj/5wCW/+UAlf/kAJT/4wCS/+IAkf/gAI//3wCO/94AjP/cAIv/2wCJ/9oAiP/YAIb/1wCF/9YA + hP/VAIL/0wCA/9IAf//RAH7/zwB8/84Ae//NAHn/zAB4/8oAdv/JAHX/yABz/8cAcv/FAHD/xABv/8MA + bf/BAGz/wABr/78Aaf+9AGj/vABm/7sAZf+6AGP/uABi/7cAYP+2AF//tABd/7MAXP+yAFr/sABZ/68A + WP+uAFb/rQBV/6sAU/+qAFL/qABP/6kAUP+qAFL/qwBT/60AVf+uAFb/rwBY/7EAWf+yAFv/swBc/7QA + Xv+2AF//twBg/7gAYv+6AGT/uwBl/7wAZv++AGj/vwBp/8AAa//BAGz/wwBu/8QAb//FAHH/xwBy/8gA + dP/JAHX/ywB3/8wAeP/NAHr/zgF7/88Cff/QAn7/0QJ//9ICgP/UAYL/1QGE/9UBhP/WAIX/1wCG/9gA + iP/bAov/3QGN/98Bjv/hAI//4gCR/+MAkv/kAJT/5gCV/+cAl//oAJj/6gCa/+sAm//sAJ3/7QCe/+8A + n//wAKH/8gOg//IAqP/2KqP//psl//+WAP//kgP//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U + AP//lAD//5QA//+SA///lgD//psk//Yro//yAKj/8gOg//AAof/vAJ//7QCe/+wAnf/rAJv/6gCa/+gA + mP/nAJf/5gCV/+QAlP/jAJL/4gCR/+AAj//fAI7/3gCM/90Ai//bAIr/2gCI/9kAh//XAIX/1gCE/9UA + gv/TAIH/0gB//9EAfv/QAHz/zgB7/80Aef/MAHj/ygB2/8kAdf/IAHP/xgBy/8UAcf/EAG//wwBu/8EA + bP/AAGv/vwBp/70AaP+8AGb/uwBl/7oAY/+4AGL/twBg/7YAX/+0AF3/swBc/7IAW/+wAFn/rwBY/64A + Vv+tAFX/qwBT/6oAUv+nAE//qQBQ/6oAUv+rAFP/rQBV/64AVv+vAFj/sQBZ/7IAW/+zAFz/tABe/7YA + X/+3AGD/uABi/7oAY/+7AGX/vABm/74AaP+/AGn/wABr/8EAbP/DAG7/xABv/8UAcf/HAHL/yAB0/8kA + df/LAHf/zAB4/80Aev/OAHv/0AB9/9EAfv/SAH//1ACB/9UAgv/WAIT/2ACF/9kAh//aAIj/2wCK/90A + i//eAI3/3wCO/+EAkP/iAJH/4wCS/+UAlP/mAJX/5wCX/+gAmP/qAJr/6wCb/+wAnf/uAJ7/7wCg//AD + n//xAKf/9Sqi//6bJf//lgD//5ID//+UAP//lAD//5QA//+UAP//lAD//5QA//+UAP//lAD//5QA//+U + AP//lAD//5QA//+SA///lgD//psk//Urov/xAKb/8AOf/+8AoP/tAJ7/7ACd/+sAm//qAJr/6ACY/+cA + l//mAJX/5ACU/+MAkv/iAJH/4ACP/98Ajv/eAIz/3QCL/9sAiv/aAIj/2QCH/9cAhf/WAIT/1QCC/9QA + gf/SAH//0QB+/9AAfP/OAHv/zQB5/8wAeP/KAHb/yQB1/8gAdP/HAHL/xQBx/8QAb//DAG7/wQBs/8AA + a/+/AGn/vQBo/7wAZv+7AGX/ugBj/7gAYv+3AGD/tgBf/7QAXv+zAFz/sgBb/7EAWf+vAFj/rgBW/60A + Vf+rAFP/qgBS/6gAT/+pAFD/qgBS/6sAU/+tAFX/rgBW/68AWP+xAFn/sgBb/7MAXP+0AF7/tgBf/7cA + Yf+4AGL/ugBj/7sAZf+8AGb/vgBo/78Aaf/AAGv/wQBs/8MAbv/EAG//xQBx/8cAcv/IAHT/yQB1/8oA + d//MAHj/zQB6/84Ae//QAHz/0QB+/9IAgP/UAIH/1QCC/9YAhP/YAIX/2QCH/9oAiP/bAIr/3ACL/94A + jf/fAI7/4QCQ/+IAkf/jAJL/5ACU/+YAlv/nAJf/6ACY/+oAmv/rAJv/7ACd/+4Anv/vA53/7wCm//Qq + of/+myX//5YA//+SA///lAD//5QA//+UAP//kgH//5MA//+UAP//lAD//5QA//+UAP//lAD//5QC//+U + AP//lAD//5QA//+SA///lQD//pwm//QspP/vAKT/7wOd/+0Anv/sAJ3/6wCb/+kAmv/oAJj/5wCX/+UA + lf/kAJT/4wCS/+IAkf/gAI//3wCO/94Ajf/dAIv/2wCK/9oAiP/ZAIf/1wCF/9YAhP/VAIL/0wCB/9IA + f//RAH7/0AB8/84Ae//NAHn/zAB4/8oAdv/JAHX/yABz/8YAcv/FAHD/xABv/8MAbv/BAGz/wABr/78A + af+9AGj/vABm/7sAZf+5AGP/uABi/7cAYP+2AF//tABe/7MAXP+yAFv/sQBZ/68AWP+uAFb/rQBV/6sA + U/+qAFL/qABP/6kAUP+qAFL/qwBT/60AVf+uAFb/rwBY/7EAWf+yAFv/swBc/7QAXv+2AF//twBh/7gA + Yv+6AGT/uwBl/7wAZv++AGj/vwBp/8AAa//BAGz/wwBu/8QAb//FAHD/xwBy/8gAdP/JAHX/ywB3/8wA + eP/NAHn/zgB7/9AAfP/RAH7/0gB//9QAgf/VAIL/1gCE/9gAhf/ZAIf/2gCI/9sAiv/dAIv/3gCN/98A + jv/hAJD/4gCR/+MAkv/kAJT/5gCV/+cAl//oAJj/6gCa/+sAm//sAJ3/7gOc/+4ApP/zKp3//psk//+W + AP//kgP//5QA//+UAP//lAD//5IB//+bAP//lwT//5MA//+UAP//lAD//5QA//+UAP//lQD//5MB//+U + AP//lAD//5QA//+SA///lQD//p0o//Mto//uAKP/7gOc/+wAnf/rAJv/6gCZ/+gAmP/nAJf/5QCV/+QA + lP/jAJL/4gCR/+AAj//fAI7/3gCM/90Ai//bAIr/2gCI/9kAhv/XAIX/1gCE/9UAgv/TAIH/0gB//9EA + fv/QAHz/zgB7/80Aef/MAHj/ygB2/8kAdf/IAHP/xwBy/8UAcP/EAG//wwBu/8EAbP/AAGv/vwBp/74A + aP+8AGb/uwBl/7oAY/+4AGL/twBg/7YAX/+0AF3/swBc/7IAWv+xAFn/rwBY/64AVv+tAFX/qwBT/6oA + Uv+nAE//qQBQ/6oAUv+rAFP/rQBV/64AVv+vAFj/sABZ/7IAW/+zAFz/tABe/7YAX/+3AGH/uABi/7oA + Y/+7AGX/vABm/74AaP+/AGn/wABr/8EAbP/DAG7/xABv/8UAcf/HAHL/yAB0/8kAdf/KAHb/zAB4/80A + ef/OAHv/0AB8/9EAfv/SAH//1ACB/9UAgv/WAIT/1wCF/9kAh//aAIj/2wCK/90Ai//eAI3/3wCO/+AA + j//iAJH/4wCS/+QAlP/lAJX/5wCX/+gAmP/qAJn/6wCb/+wDmv/sAKP/8ima//6ZIP//lgD//5ID//+U + AP//lAD//5QA//+RA///oQD//Wtf//57Nf//mgD//5MC//+UAP//lAD//5UC//+VLP//mQD//5IB//+U + AP//lAD//5QA//+SA///lQD//p0n//Itof/sAKH/7AOa/+sAm//pAJr/6ACY/+cAl//mAJX/5ACU/+MA + kv/iAJH/4ACP/98Ajv/eAIz/3QCL/9sAif/aAIj/2QCG/9cAhf/WAIT/1QCC/9QAgf/SAH//0QB+/9AA + fP/OAHv/zQB5/8wAeP/KAHb/yQB1/8gAc//GAHL/xQBw/8QAb//DAG3/wQBs/8AAa/+/AGn/vgBo/7wA + Zv+7AGX/ugBj/7gAYv+3AGD/tgBf/7QAXf+zAFz/sgBb/7AAWf+vAFj/rgBW/60AVf+rAFP/qgBS/6cA + T/+pAFD/qgBS/6sAU/+tAFX/rgBW/68AWP+wAFn/sgBb/7MAXP+1AF3/tgBf/7cAYP+4AGL/ugBj/7sA + Zf+8AGb/vgBo/78Aaf/AAGv/wQBs/8MAbv/EAG//xQBx/8cAcv/IAHT/yQB1/8oAdv/MAHj/zQB5/84A + e//PAHz/0QB+/9IAf//TAIH/1QCC/9YAg//XAIX/2QCG/9oAiP/bAIn/3ACL/94AjP/fAI7/4ACP/+EA + kf/jAJL/5ACU/+UAlf/nAJb/6ACY/+kAmv/rA5j/6wCh//Apmf/+mSD//5YA//+SA///lAD//5QA//+U + AP//kAP//6AA//1vVf/4A8P//oBA//+aAP//kwP//5QA//+SAv//oAD/+0WA//xfXf//owD//5ED//+U + AP//lAD//5QA//+SA///lQD//p0n//AtoP/qAJ//6wOY/+kAmf/oAJj/5gCW/+UAlf/kAJP/4gCS/+EA + kP/gAI//3wCO/94AjP/cAIv/2wCJ/9oAiP/YAIb/1wCF/9YAg//VAIL/0wCA/9IAf//RAH3/zwB8/84A + e//NAHn/zAB4/8oAdv/JAHX/yABz/8YAcv/FAHD/xABv/8MAbf/BAGz/wABr/78Aaf+9AGj/vABm/7sA + Zf+5AGP/uABi/7cAYP+1AF//tABd/7MAXP+yAFr/sABZ/68AV/+uAFb/rABV/6sAU/+qAFL/pwBP/6gA + UP+qAFL/qwBT/6wAVf+uAFb/rwBX/7AAWf+yAFr/swBc/7QAXf+2AF//twBg/7gAYv+5AGP/uwBl/7wA + Zv+9AGj/vwBp/8AAa//BAGz/wgBu/8QAb//FAHD/xgBy/8gAc//JAHX/ygB2/8sAeP/NAHn/zgB7/88A + fP/RAH7/0gB//9MAgP/VAIL/1gCD/9cAhf/YAIb/2gCI/9sAif/cAIv/3gCM/98Ajf/gAI//4QCQ/+MA + kv/kAJP/5QCV/+YAlv/oAJj/6QOX/+kAn//vKpf//pog//+WAP//kgP//5QA//+UAP//lAD//5AD//+g + AP/8b1f/9wOy//cAtf/9ekn//5oA//+TA///lAD//5ED//+gAP/7Qmf/9gDA//xvT///oAD//5ED//+U + AP//lAD//5QA//+SA///lQD//p0n/+8tnv/pAJ3/6QOX/+gAmP/mAJb/5QCV/+QAk//iAJL/4QCQ/+AA + j//fAI3/3QCM/9wAiv/bAIn/2gCI/9gAhv/XAIX/1gCD/9QAgv/TAID/0gB//9AAff/PAHz/zgB7/80A + ef/LAHj/ygB2/8kAdf/IAHP/xgBy/8UAcP/EAG//wgBt/8EAbP/AAGr/vwBp/70AaP+8AGb/uwBk/7kA + Y/+4AGL/twBg/7YAX/+0AF3/swBc/7IAWv+wAFn/rwBX/64AVv+sAFT/qwBT/6oAUf+nAE//qQBQ/6oA + Uf+rAFP/rABU/64AVv+vAFf/sABZ/7IAWv+zAFz/tABd/7YAX/+3AGD/uABi/7kAY/+7AGX/vABm/70A + Z/+/AGn/wABq/8EAbP/CAG3/xABv/8UAcP/GAHL/xwBz/8kAdf/KAHb/ywB3/80Aef/OAHr/zwB8/9AA + ff/SAH//0wCA/9QAgv/VAIP/1wCF/9gAhv/aAIf/2wCJ/9wAiv/dAIz/3gCN/+AAj//hAJD/4gCS/+QA + k//lAJT/5gCW/+gClf/nAJ3/7iqW//6aH///lgD//5ID//+UAP//lAD//5QA//+QA///oAD/+29W//UD + s//2AqP/9gC0//xbTP//nwD//5ID//+UAP//kgP//54A//xsZ//1ALL/9QOv//tsUf//oAD//5ED//+U + AP//lAD//5QA//+SA///lQD//p0m/+4unP/nAJz/5wKV/+YAlv/lAJT/4wCT/+IAkf/hAJD/4ACO/98A + jf/dAIz/2wGK/9kBiP/XAYb/1gCF/9YAg//TAIL/0gGB/9MAgP/SAH//0AB9/88AfP/OAHr/zAB5/8sA + d//KAHb/yAB0/8cBc//FAXH/wwFw/8IBbv/CAW3/wQBs/8AAav+/AGn/vQBn/7wAZv+7AGT/uQBj/7gA + Yf+3AGD/tgBf/7QAXf+zAFv/sgBa/7AAWf+vAFf/rgBW/6wAVP+rAFP/qgBR/6cAT/+oAFD/qgBS/6sA + U/+sAFT/rgBW/68AV/+wAFn/sQBa/7MAXP+0AF3/tQBe/7cAYP+4AGL/uQBj/7oAZP+8AGb/vQBn/74A + af/AAGr/wQBr/8IAbf/DAG//xQBw/8YAcv/HAHP/yQB0/8oAdv/LAHf/zQB5/84Aev/PAHz/0AB9/9IA + f//TAID/1ACB/9UAg//XAIT/2ACG/9kAh//aAIn/3ACK/90Ai//eAI3/3wCO/+EAkP/iAJH/4wCS/+QA + lP/mAZT/5gCZ/+wplP/+miD//5YA//+SA///lAD//5QA//+UAP//kAL//6AA//tuVv/zA7H/9AGk//UE + o//1ALP/+2Ra//+eAP//kgP//5QA//+SA///ngD/+2Zc//QAsv/0AqH/8gKw//tsUf//oAD//5AD//+U + AP//lAD//5QA//+SA///lQD//p0n/+wtm//mAJj/5gKU/+QAlP/jAJL/4gCR/+ABj//dAY3/3AGL/9wA + iv/eAIr/4gCM/+UAjf/iAIz/2weK/98Aif/dAIT/0gB+/88Bff/PAX3/zgF7/8wBef/KAXj/yQB2/8kA + df/JAHT/ygBz/8oAcv/MAHL/ywBx/8MAbP+/AWv/wABq/74Aaf+9AGf/vABm/7oAZP+5AGP/uABh/7cA + YP+1AF//tABd/7MAXP+xAFr/sABZ/68AV/+tAFX/rABU/6sAU/+pAFH/pwBO/6gAUP+qAFH/qwBT/6wA + VP+tAFb/rwBX/7AAWf+xAFr/swBb/7QAXf+1AF7/tgBg/7gAYf+5AGP/ugBk/7wAZf+9AGf/vgBp/8AA + av/BAGv/wgBt/8MAbv/FAHD/xgBx/8cAc//IAHT/ygB2/8sAd//MAHj/zQB6/88Ae//QAH3/0QB+/9MA + gP/UAIH/1QCC/9YAhP/YAIX/2QCH/9oAiP/bAIr/3QCL/94Ajf/fAI7/4ACP/+IAkf/jAJL/5AGT/+QA + lP/pG5v//p8g//+UAP//kgP//5QA//+UAP//lAD//5AC//+gAP/6blX/8QOv//IBof/zAaT/9AKj//QA + sv/7Z2P//54A//+SA///lAD//5ID//+eAP/7YlH/8wCx//MDof/yAaL/8QKu//prUP//oAD//5ED//+U + AP//lAD//5QA//+TBP//kwD//6Mn/+kdnv/jAZL/4QKS/+AAkf/hAJD/5QCQ/+kAkv/qAJP/5AWR/9IO + if+1Gnv/kiVp/3AzWf9YO07/bzBY/6kec//WCYX/3ACC/9QAff/TAHz/1QB8/9YAfP/UAHv/zwV6/8gI + d/+9D3P/sx10/6IaaP+fGGX/vw1x/8gAbf+9AWn/vgBp/70AZ/+8AGX/ugBk/7kAY/+4AGH/tgBg/7UA + Xv+0AF3/sgBb/7EAWv+wAFn/rwBX/60AVf+sAFT/qwBS/6kAUf+nAE7/qABQ/6kAUf+rAFL/rABU/60A + Vf+uAFf/sABY/7EAWv+yAFv/tABd/7UAXv+2AGD/twBh/7kAYv+6AGT/uwBl/70AZ/++AGj/vwBq/8AA + a//CAG3/wwBu/8QAcP/GAHH/xwBy/8gAdP/JAHX/ywB3/8wAeP/NAHr/zgB7/9AAff/RAH7/0gB//9MA + gf/VAIL/1gCE/9cAhf/ZAIb/2gCI/9sAif/cAIv/3QCM/98Ajf/gAI7/4QCQ/+IAkv/kAJP/5QGT/+YH + m//0YWP//6EC//+RAf//lAH//5QA//+QAv//oQD/+XBZ/+8Drf/wAZ//8QGi//IAo//zAqH/8gCw//pt + a///ngD//5ID//+UAP//kgP//54A//peSP/yAK//8gKg//EBov/wAZ//7wKs//lpTP//oAD//5ED//+U + AP//lAH//ZIA//2iAf/yYWD/5gaa/+sAlv/uAJj/7gCZ/+UJlf/PGIz/rB94/4MqY/9eNk//RjxC/0FM + Rf9UZFr/S1dO/yQrJv8iLyf/LTsz/1Q1Sv+TJGj/vhd8/70Rd/+kI3D/jC1n/3U4X/9jRFf/Uj5K/0E+ + QP81Ozj/Lzo0/yc0Lf9DND7/pCNr/8oAbv+9AGf/vAFn/7sAZf+6AGT/uQBi/7cAYf+2AF//tQBe/7QA + Xf+yAFv/sQBa/7AAWP+uAFf/rQBV/6wAVP+rAFL/qQBR/6cATv+oAE//qQBR/6sAUv+sAFT/rQBV/64A + V/+wAFj/sQBa/7IAW/+0AFz/tQBe/7YAX/+3AGH/uQBi/7oAZP+7AGX/vABn/74AaP+/AGn/wABr/8IA + bP/DAG7/xABv/8UAcf/HAHL/yAB0/8kAdf/KAHb/zAB4/80Aef/OAHv/zwB8/9EAfv/SAH//0wCA/9QA + gv/WAIP/1wCE/9gAhv/ZAIf/2gCJ/9wAiv/dAIz/3gCN/98Ajv/hAJD/4gCR/+MAkv/kAJP/5QCT/+UA + pP/0YGj//6IB//+RAf//kAP//6EA//lwWv/tA6z/7wGd//ABoP/wAKH/8QCi//ICoP/xAK//+mZs//+e + AP//kgP//5QA//+SA///ngD/+l1E//AArv/xAp//8ACh/+8Bn//uAZ7/7AKo//dqSf/9oQD//JEC//6S + Af//ngT//11u//ABrP/oCJj/zBGJ/6Yfd/97LV//VThL/z9BQP8/TUT/V2Zc/3Z/ef+VmZb/srGy/8PB + w/+/v8D/mJiY/1ZTVP8uKyz/Ji0p/yY2Lf86PTz/NDU2/zI8NP80OjD/NjUs/zU1L/87Pzz/UlNS/29v + b/+JiIn/hoOE/0hMSf8oMy7/fS1b/8UHbv+9AGX/ugFl/7oAY/+4AGL/twBh/7YAX/+1AF7/tABc/7IA + W/+xAFr/sABY/64AV/+tAFX/rABU/6oAUv+pAFH/pgBO/6gAT/+pAFH/qgBS/6wAU/+tAFX/rgBX/68A + WP+xAFn/sgBb/7MAXP+1AF7/tgBf/7cAYf+4AGL/ugBk/7sAZf+8AGb/vQBo/78Aaf/AAGv/wQBs/8MA + bv/EAG//xQBw/8YAcv/HAHP/yQB1/8oAdv/LAHj/zAB5/84Aev/PAHz/0AB9/9IAfv/TAID/1ACB/9UA + g//WAIT/2ACF/9kAh//aAIj/2wCK/9wAi//eAIz/3wCO/+AAj//hAJD/4gCS/+QAk//lAZT/5gKS/+UA + o//0YGn//6EA//+gAP/4cFr/6wOp/+0Bmv/uAZ7/7gCf/+8AoP/wAKH/8AKf//AArf/3PGL//5wC//+Q + Bf//kgL//5AF//+cAv/5WkD/7wCs/+8Dnv/tAZ//6wGe/+wAnP/vAJz/9ACq//9lUf//oAH//50E/9B6 + Wv+WLIL/ZC1N/081R/86Ozv/O0tA/1BfVf9ze3b/lpeW/7e1t//FwsT/vr6//9bW1//a29v/1dfX/8DC + wf+5u7v/v8LB/5KUkv9LSUn/LSkr/ywrK/85NjX/P0tP/0FncP89jp3/QY6g/6Cipf/Hycj/z9HR/9XW + 1v/Mz8//wMDB/3Z0dP8oNy7/XDRM/78Vcf+/AGX/twFj/7kAYv+3AGD/tgBf/7QAXv+zAFz/sgBb/7AA + Wf+vAFj/rgBW/60AVf+sAFP/qgBS/6kAUP+mAE7/qABP/6kAUP+qAFL/qwBT/60AVf+uAFb/rwBY/7AA + Wf+yAFv/swBc/7QAXf+2AF//twBg/7gAYv+5AGP/uwBk/7wAZv+9AGf/vgBp/8AAav/BAGz/wgBt/8QA + b//FAHD/xgBx/8cAc//IAHT/ygB2/8sAd//MAHj/zQB6/88Ae//QAH3/0QB+/9IAf//UAIH/1QCC/9YA + hP/XAIX/2ACG/9oAiP/bAIn/3ACK/90Ai//eAI3/3wCO/+EAj//iAJH/4wCS/+QAk//lAZX/5gKS/+UA + pf/1YmH/+HJU/+kDqP/rAJj/7AGc/+wAnf/tAJ7/7gCf/+4An//vAp3/7gCs//Y/XP//pwD//5oA//+d + AP//mwD//qgA//dhNv/tAKv/8gCe//cAo//6AKX/9QSk/+QTnP/EIoz/ji58/61xGf+JWRb/JC06/zFB + M/9IVEv/dXt3/5qbmv+1srT/xsTF/9LS0//R0tL/ubq6/8LCw//Q0ND/xsXG/6SjpP+Hhof/t7e4/9DR + 0P/DxsX/ub28/7S3tv+foaH/kI2M/z2es/83z+v/OdHy/z3R+P9fyuH/2tbW/9rb2//S0tL/yMjI/8vM + zP/Kzc3/zM7O/6Cdnv86RT7/SjtF/7EQZ/+/AGT/tgFh/7cAYP+1AF//tABd/7MAXP+yAFr/sABZ/68A + WP+uAFb/rQBV/6sAU/+qAFL/qQBQ/6YATf+nAE//qQBQ/6oAUv+rAFP/rABU/64AVv+vAFf/sABZ/7EA + Wv+zAFz/tABd/7UAX/+3AGD/uABh/7kAY/+6AGT/vABl/70AZ/++AGn/vwBq/8AAa//CAG3/wwBu/8QA + cP/GAHH/xwBy/8gAdP/JAHX/ywB3/8wAeP/NAHn/zgB7/88AfP/RAH7/0gB//9MAgP/VAIL/1QCD/9cA + hP/YAIb/2QCH/9oAiP/bAIr/3ACL/94AjP/fAI7/4ACP/+EAkP/iAJH/4wCT/+QAlP/lAJX/5gCU/+YA + nv/nAKD/6QCY/+oBmv/rAJv/6wCc/+wAnf/tAJ3/7QCe/+4Cnf/tAKb/8i10//h1Mv/3azX/+ms0//5m + OP//bjf//z9l//QCrP/iD5n/wB6K/5Mscf9lNFX/QDc9/y47Mf8yQjf/UFNY/3J1ef+ZmJf/t7S2/8vI + yv/S0tL/2NjY/93d3f/d3d3/1dXV/8PCw/+pqKn/hoWG/2NjY/9GRkf/Ozs7/ywsLP85OTr/c3N0/7i6 + u//Jy8r/vcHB/9rW1f+vy9H/NsPl/1HL6/811/D/Odbw/2isuv+soJ7/gIGC/2hnaP9MTE3/a2xt/8HD + w//P0dH/xMjI/7SztP9QWFL/PS84/6wNYf++AGP/tAFf/7UAXv+0AF3/swBb/7EAWv+wAFn/rwBX/64A + Vv+sAFT/qwBT/6oAUf+pAFD/pgBN/6cATv+oAFD/qgBR/6sAU/+sAFT/rQBV/68AV/+wAFn/sQBa/7IA + W/+0AF3/tQBe/7YAYP+3AGH/uQBj/7oAZP+7AGX/vQBn/74AaP+/AGn/wABr/8IAbP/DAG7/xABv/8UA + cf/GAHL/yABz/8kAdf/KAHb/ywB4/8wAef/OAHr/zwB8/9AAff/SAH7/0wCA/9QAgf/VAIL/1gCE/9cA + hf/YAIb/2gCH/9sAif/cAIr/3QCL/94Ajf/fAI7/4ACP/+EAkP/iAJL/4wCT/+QAlP/lAJX/5gGV/+cB + lf/oAJj/6QCZ/+oAmv/qAJv/6wCb/+oBnP/qAZv/6gCc/+0AnP/yAKP/9wCs//oAr//yAK3/3g2j/7od + kv+NLHT/Xi1N/zw0Ov8uOzP/N0g8/1NeVv96fHn/npud/7m2t//Lysn/1tXU/9vb2//d3d3/29vb/9LS + 0/+9vb7/np6e/3p5ev9ZWVn/RERF/zo6Ov83Nzf/OTk5/zk5Of82Njb/ODg4/0pKSf9DQ0L/RkVF/319 + fv+3urv/2NLR/321wP8b3/f/DeP9/wDa+P8bxd7/RkpL/1RTUv9RUVD/QkNC/zo6Ov80NDT/SEhK/6Wm + p/+2ubj/lJqb/8bFxv9gZ2L/PjA4/6sNYP+8AGD/swFe/7QAXf+yAFv/sQBa/7AAWP+vAFf/rQBV/6wA + VP+rAFP/qQBR/6gAUP+lAE3/pwBO/6gAUP+qAFH/qwBT/6wAVP+tAFX/rgBX/7AAWP+xAFr/sgBb/7MA + XP+1AF7/tgBf/7cAYf+4AGL/ugBk/7sAZf+8AGb/vQBo/78Aaf/AAGr/wQBs/8IAbf/EAG//xQBw/8YA + cf/HAHP/yAB0/8oAdv/LAHf/zAB5/80Aev/OAHv/0AB9/9EAfv/SAH//0wCB/9QAgv/WAIP/1wCE/9gA + hv/ZAIf/2gCI/9sAiv/cAIv/3gCM/98Ajf/fAI7/4QCQ/+IAkf/jAJL/4wCT/+QAlP/lAJX/5gCW/+cA + l//mAZf/5gGX/+cAmP/qAJr/8ACd//YAof/4AKT/8Aqi/9kamP+1K4T/hitl/1k0Sv86OTf/Lz8x/ztM + Pv9YY1v/gIKA/6Sho/++urz/zMrL/9XU1f/a2tr/3d3d/9zb2//R0dH/ubm5/5mZmv91dXX/V1dY/0JC + Qv85OTn/OTk5/zo6Ov86Ojr/Nzc3/zIyMv8tLS3/KCgo/x8fH/8ZGRn/Kioq/zw9Pf9TU1L/QUBA/0xN + Tf9TTUz/QF9n/wWw1/8hjKv/Ko2r/0B6if9QR0X/U1RU/0ZFRf80MzP/JiYm/z09Pf9AQED/Ojo6/4iL + jP+eoqL/x8rK/83Nzf9pcGv/PzI7/6wPYf+5AF7/sgFc/7IAW/+xAFn/sABY/64AV/+tAFX/rABU/6sA + Uv+pAFH/qABP/6UATP+nAE7/qABP/6kAUf+qAFL/qwBU/60AVf+uAFb/rwBY/7EAWf+yAFv/swBc/7QA + Xf+1AF//twBg/7gAYv+5AGP/uwBk/7wAZv+9AGf/vgBp/78Aav/BAGv/wgBt/8MAbv/EAHD/xgBx/8cA + cv/IAHT/yQB1/8sAdv/MAHj/zQB5/84Ae//PAHz/0AB9/9IAfv/TAID/1ACB/9UAgv/WAIT/1wCF/9gA + hv/aAIf/2gCJ/9wAiv/dAIv/3gCM/98Ajv/gAI//4QCQ/+IAkf/iAZH/4gGS/+IBk//jAJP/5wCW/+0A + mf/zAJ3/9AKg/+oJnP/SFJH/rCN9/34vY/9TNkr/Nzo4/y9ANP8/T0T/X2dh/4aHhf+npKb/wLy//87M + zf/V1dX/29vb/97e3v/b29v/0M/Q/7a2tv+VlZb/cnJz/1RUVP9BQUH/Ojo6/zk5Of87Ozv/Ojo6/zc3 + N/8yMjL/LCws/yMjJP8eHh7/GRkZ/xQTFP8XFxf/LCwr/2JgXv9ycG3/PDw7/zg4Of89PT3/S0xL/0VB + QP8+TlL/KY+m/0CHl/9JZmz/Pjs6/zAxMf8iIiH/GBgY/xQUFP8VFRX/GRkZ/zMzM/9GRkX/Ozs7/2dp + bP/O0NH/xsnJ/8rKyv9ob2r/TT9I/7YPZv+0AFr/sQFb/7EAWf+vAFj/rgBW/60AVf+rAFP/qgBS/6kA + Uf+oAE//pQBM/6YATv+oAE//qQBQ/6oAUv+rAFP/rQBU/64AVv+vAFf/sABZ/7EAWv+zAFz/tABd/7UA + Xv+2AGD/uABh/7kAY/+6AGT/uwBl/70AZ/++AGj/vwBq/8AAa//CAGz/wwBu/8QAb//FAHD/xgBy/8gA + c//JAHX/ygB2/8sAd//MAHn/zQB6/88Ae//QAHz/0QB+/9IAf//TAID/1ACC/9UAg//XAIT/2ACF/9kA + h//aAIj/2wCJ/9wAiv/dAIv/3QGM/90Bjf/dAY3/3wCP/+MAkf/qAJT/8ACZ//ABm//kC5j/yRmM/6Mp + eP92NF//SzFC/zQ2Nf8yQjf/RVNJ/2huaf+NjYz/raqr/8K/wf/Qzs//2NfY/9zc3P/e3d3/29vb/8vL + y/+ysrL/kZGR/29vb/9RUVH/Pz8//zk5Of86Ojr/Ozs7/zo6Ov83Nzf/MTEx/ysrK/8kJCX/HR0e/xUW + Fv8XFxj/KSko/zc2Nv9JSEf/cnBu/5OQjf+hn5z/lJKP/2dlZP8yMTH/LS0t/zIyMv80NDT/SEhI/0dE + Q/9BPDr/Ojc1/y4oJ/8pKSr/KSkp/x4eHv8VFRX/FhYW/xcXF/8WFhb/FhYW/yoqKv9GRkb/PT08/2Fj + ZP/Fx8j/wMPD/8rJyv9faWL/WjVK/7sKZP+wAFj/sAFZ/68AV/+uAFb/rABU/6sAU/+qAFL/qQBQ/6cA + T/+kAEz/pgBN/6cAT/+oAFD/qgBR/6sAU/+sAFT/rQBV/68AV/+wAFj/sQBa/7IAW/+0AFz/tQBe/7YA + X/+3AGH/uABi/7oAZP+7AGX/vABm/74AaP+/AGn/wABq/8EAbP/CAG3/wwBv/8QAcP/GAHH/xwBz/8gA + dP/JAHX/ywB3/8wAeP/NAHn/zgB7/88AfP/QAH3/0QB+/9MAgP/UAIH/1QCC/9YAg//XAIX/2ACG/9gB + h//YAYj/2AGI/9oAif/fAIz/5gCQ/+sAlP/qA5b/3Q+S/8Efh/+ZJnD/bCpV/0czQf80Ozb/NUY7/0tY + T/9yeHP/lpaW/7Swsv/HxMb/0tDR/9jY2P/d3dz/3t7e/9nZ2f/IyMj/ra2t/42Njf9paWr/Tk5O/z4+ + Pv85OTn/Ojo6/zs7Ov86Ojr/Nzc3/zExMf8rKyv/IiIi/xsbG/8XFxf/FhYX/yIhIf82NTT/WVdV/3Nw + bv9fXlz/WllY/2JhYP9kY2L/UVBP/zc2Nv8lJSX/JCQk/y0tLf8rKyv/KSkp/ywsLP8xMTH/Li8v/yss + LP8tLi7/MDEy/zAwMP8wMDD/Li4t/yUlJf8dHR3/GRkY/xUVFf8VFRX/FBQU/yIiIv9ERET/QEBA/1la + W//Gx8j/wMTE/8TCw/9SYFj/dS9V/7sBXv+uAVf/rwBX/60AVf+sAFT/qwBT/6oAUf+oAFD/pwBO/6QA + S/+mAE3/pwBO/6gAUP+pAFH/qwBS/6wAVP+tAFX/rgBX/68AWP+xAFn/sgBb/7MAXP+0AF3/tgBf/7cA + YP+4AGL/uQBj/7sAZP+8AGb/vQBn/74Aaf/AAGr/wQBr/8IAbf/DAG7/xABv/8UAcf/GAHL/yABz/8kA + df/KAHb/ywB3/8wAeP/NAHr/zwB7/9AAfP/RAH7/0gB//9MAgP/TAYH/0wGC/9QBg//WAIT/2wCH/+IA + i//nAI//5QaS/9UQjP+4GH3/jyZp/2UvUv9EN0D/N0I7/0FRRv9ea2L/gYaC/5ybm//AvL7/3drc/9TT + 0//X19f/3d3d/9/f3//Z2dn/x8fH/6urrP+HiIn/ZWVm/0pKS/89PT3/OTk5/zo6Of88PDv/OTk5/zY1 + Nf8xMTH/Kysr/yMjJP8bGxz/FRUV/xgYGP8uLSz/QUA//1ZVU/91c3D/iYaC/4WDgP90cXD/Q0JB/zEw + Mf85ODf/PDs6/zUzMv8nJyf/LS0t/zM0M/8zMzL/MTEx/zQ0NP8wMDD/LS0t/ywsLP8vLy//MzMz/zQ0 + NP8zMzP/MjIy/zIyMv8wMDD/Li4u/yoqKv8lJSb/Jycn/yAgIP8hISH/Hh4e/xwcHP9BQkL/RERD/19f + Yf/DxcX/x8vL/7e2tv9HU03/lyZh/7YAWP+tAVb/rQBV/6wAVP+qAFL/qQBR/6gAT/+nAE7/pABL/6UA + TP+mAE7/qABP/6kAUf+qAFL/qwBT/60AVf+uAFb/rwBY/7AAWf+yAFr/swBc/7QAXf+1AF7/tgBg/7gA + Yf+5AGP/ugBk/7sAZf+8AGf/vgBo/78Aaf/AAGv/wQBs/8IAbf/EAG//xQBw/8YAcf/HAHP/yAB0/8kA + df/LAHf/zAB4/80Aef/OAHr/zgF7/84BfP/PAX3/0gB//9cAgf/dAIX/4QCJ/94Eif/NEIX/rx54/4cq + Zf9fNE//QTk//zhBO/9HV0z/aXRs/5CTkP+0sbL/ycbI/9LP0f/W1dX/1tbX/7Kzs/+5ubj/t7e3/8jI + yP+srKz/hIWF/2JiYv9JSUr/PDw8/zk5Of86Ojr/Ozs7/zk5Of81NTX/Ly8v/ykpKf8hISL/Ghoa/xcX + F/8ZGBn/JSUk/z49PP9hX1z/e3l2/2NhYP9QT0//U1JR/01MS/81NTT/Ly8v/x8gIP8yMTH/VVNR/1pY + Vv9eXFr/UVBO/0BAQP85OTj/Ojo6/zw8PP88PDz/MzMy/y8vL/8xMTH/MzMz/zQ0NP80NDT/MzMz/zQ0 + NP80NDT/NDQ0/zIyMv8wMDD/ODg3/0hHRv9TUlD/SEdF/ycnJ/8oKCj/IiIi/yEhIf9BQUH/RUVF/2Zo + af/Kzc3/0tTU/5ugnP9SSU7/sBBh/64AVP+sAVX/qwBT/6oAUv+pAFD/pwBP/6YATf+kAEv/pQBM/6YA + Tf+nAE//qQBQ/6oAUf+rAFP/rABU/60AVv+vAFf/sABY/7EAWv+yAFv/tABd/7UAXv+2AF//twBh/7gA + Yv+6AGP/uwBl/7wAZv+9AGf/vgBp/8AAav/BAGv/wgBt/8MAbv/EAG//xQBx/8cAcv/IAHP/yAB0/8kB + df/JAXb/ygB3/80Aef/TAHv/2QCA/9wAg//XB4T/xRSA/6cjdP+ALmH/Vy1H/z44PP85RT7/TFpQ/295 + cv+XmZf/uLW2/8zIyv/U0tP/19bX/9ra2v/e3t7/4eHh/9/f3//Gxsb/YmNj/3R0dP9RUVL/SEhI/zw8 + PP86Ojr/Ozs7/zs7O/84ODj/NDQ0/y4uLv8nKCj/ICAh/xkZGv8VFRX/GRkZ/ywrKv9EQ0H/XFpY/3Vz + cP+HhIH/gX98/25sav9BQED/Ly4u/zo4OP9DQkH/Q0JB/zMyMf8xMDD/MzMz/0A/P/9SUVD/SUhH/0JC + Qv8+Pj7/PT09/zo6Ov83Nzf/MTEx/wwLC/8DAgL/EhAR/zQ0NP8zMzP/NDQ0/zQ0NP80NDT/NDQ0/zMz + M/80NDT/MDAw/0ZGRf9aWVb/S0lI/zU1Nf8wMDD/Kioq/yoqKv8rKyv/KCgo/ycnJ/9GRkf/RUVF/3h7 + ff/Ex8b/rKmq/3uHgP9zMlX/uAJb/6oBU/+rAFP/qgBR/6gAUP+nAE//pgBN/6MASv+kAEv/pgBN/6cA + Tv+oAFD/qQBR/6sAUv+sAFT/rQBV/64AV/+vAFj/sQBZ/7IAWv+zAFz/tABd/7YAX/+3AGD/uABi/7kA + Y/+6AGT/uwBl/70AZ/++AGj/vwBp/8AAa//BAGz/wgBt/8MAbv/EAXD/xAFx/8UAcv/JAHT/zwB3/9UA + e//YAX//0Ap+/70Yev+dJ27/di9a/1IxRf88PDz/PEpB/1JgV/91fnj/m52b/7y5uv/Oy8z/19XW/9jY + 2P/b29v/39/f/+Hh4f/c29v/yMjI/6ioqP+FhYX/YmJi/0lJSf9DQ0P/Pz8//z8/P/89PTz/Ojo5/zQ0 + NP8vLy//KSkp/yAhIf8YGRn/FBUV/xwcHP8uLi3/REJB/2NgXv9+e3j/fXp3/2ZlY/9WVVX/Q0NC/zQ0 + NP8tLS3/IiMj/zExMf9cW1n/V1VU/1ZVU/9UUlH/S0pJ/zw7O/87Ozv/PT09/zk5Of82Njb/MjMy/y4v + Lv8uLi7/MTEx/zExMf8vLy//Gxoa/yMjI/8rKyv/MjIz/zMzM/80NDT/NDQ0/zQ0NP80NDT/MzMz/zMz + M/8yMjL/NDQ0/y8vL/8rKyv/LS0t/ywsLP8rKyv/Kysr/ysrK/8sLCv/KSkp/ykpKv9KSkr/TExN/4GD + g/+CgYD/r7Cw/2BlY/+cD1f/sABT/6oBUv+pAFH/qABP/6cATv+mAE3/owBK/6QAS/+lAEz/pgBO/6gA + T/+pAFD/qgBS/6sAU/+sAFX/rgBW/68AV/+wAFn/sgBa/7MAW/+0AF3/tQBe/7YAX/+3AGH/uABi/7oA + Y/+7AGX/vABm/70AaP++AGn/vgFq/78Ba//AAGz/xABu/8oAcf/PAHX/0AB3/8UJdf+uFm7/jSRh/2wm + T/9LM0H/OT07/z5MQ/9XY1v/fIN+/6Kiof+/vL3/0M3O/9fV1v/b2tr/3t7e/+Dg4P/f39//1NTU/729 + vf+bnJz/enp6/1paW/9ERET/Ozs7/zk5Of87Ozv/PDw8/zg4OP80NDT/Ly8v/ykpKf8hISH/GRkZ/xYW + Fv8dHBz/Kyoq/0VDQv9lY2H/cG1r/2VkYv9lY2L/WVhX/0lISP8qKir/Q0FA/1NRT/8xMTH/Kioq/zg4 + OP80NDT/QUFA/01MS/9FRET/Pz4+/z09Pf87Ozv/Nzc3/zMzM/8uLi7/LS0t/zExMf85OTn/SkpK/0RE + RP8vLy//MzMz/zIyMv83Nzf/NjY2/zU1NP8zMzP/MzMz/zQ0NP8zMzP/MzMz/zMzM/8zMzP/MzMz/zMz + M/8yMjL/MjIy/zExMf8wMDD/Ly8u/ywtLP8pKCr/JyYp/yUkKP8uLi//OTk5/y8vMP9QUFD/W1xc/2Zm + Zv+trrD/maWf/2w/V/+0BVr/qAFR/6kAUf+oAE//pgBN/6UATP+iAEn/pABK/6UATP+mAE3/pwBP/6gA + UP+qAFH/qwBT/6wAVP+tAFX/rgBX/7AAWP+xAFr/sgBb/7QAXP+0AF7/tgBf/7cAYP+4AGH/uQBj/7oA + ZP+7AWb/uwFm/74AZ//EAGr/ygBu/8oAcf/ACW//qRVo/4chW/9jLEv/RzZA/z1EQP9EU0r/VGBZ/4GG + gv+mpaX/xMDC/9TQ0v/Z2Nn/3Nvc/97e3v/g4OD/29va/8zMzP+ysrL/kJCQ/2xsbf9RUVH/Pz8//zg4 + OP86Ojr/Ozs7/zs7O/85OTj/NDQ0/y4uLv8oJyf/ICAg/xgZGf8VFRX/Gxsb/ywrK/9HRkT/Y2Jf/3t5 + dv99e3j/cXBt/11cWv84Nzf/RkRD/0lHRv8pKCj/LC0t/zQ0NP85ODj/T05N/0A/P/82Njb/Pj4+/zw8 + PP8+Pj3/OTk5/zU1Nf8xMTH/Li4u/y0tLf8yMjL/PDw8/0lJSf9XWFj/Y2Nj/2pqav9tbW3/ampq/zQ0 + NP8xMTH/MjIy/zExMf8xMTH/MjIy/zMzM/8zMzP/MzMz/zMzM/8zMzP/MzMz/zMzM/8zMzP/MzMz/zMz + M/8zMzP/MjIx/y8vMP8sKy3/Kyst/zc6Mv9HTDv/VFw//zM0Mf8/P0D/KSkp/zc3N/9VVVX/Y2Rl/73B + wf/GyMf/bXdz/5gZWf+uAFD/qAFQ/6cAT/+mAE3/pQBM/6IASf+jAEr/pABL/6YATf+nAE7/qABP/6kA + Uf+qAFL/rABU/60AVf+uAFb/rwBY/7AAWf+xAFr/swBb/7QAXf+1AF7/tgBf/7gAYf+5AGL/uQBk/7wA + ZP/GAGv/vgts/6cXZv+FIln/Yy5M/0g4Qf8/RkL/TFtS/2t2b/+QlJH/sK6u/8jFxv/W09X/2tnZ/93c + 3f/f39//3t7e/9bW1v/ExMT/qamp/4aGhv9iYmL/SkpK/zw8PP85OTn/OTk5/zs7O/87Ozv/ODg4/zQ0 + NP8vLy//KCgo/x8fH/8XFxj/FhYW/x0dHf8vLy7/SUdG/2RiX/9zcW//eXd0/21rav9TUlH/PT08/y0s + LP8oKCj/Jygo/zAvL/9RT07/VFJR/z8+Pv85OTn/Pj4+/zo7Ov89PT3/PT08/zo6Ov81NTX/MjIy/y4u + Lv8uLi7/NDQ0/z8/P/9NTU3/Wlpa/2VlZP9ra2v/bGxs/21tbf9qamr/aGho/2RkZP9vb2//SEhI/y0t + Lf8zMzP/MjIy/zIyMv8yMjL/MjIy/zIyMv8zMzP/MzMz/zMzM/8zMzP/MzMz/zMzM/8zMzP/MjIy/zIy + Mv8yMjL/OTo2/0hOPf9dZ0f/Z3JM/1dgQf9HTDn/LCwr/ygoKP8sLCz/KSkp/0NDQ/9ZWVn/lJeZ/8/R + 0v+cqaP/bjdU/7EBVP+mAU//pwBO/6UATf+kAEv/oQBI/6MASf+kAEv/pQBM/6YATv+nAE//qQBQ/6oA + Uv+rAFP/rQBU/60AVv+vAFf/sABY/7EAWv+yAFv/swBc/7UAXv+2AF//twBg/7gCY/+7AmL/tRRr/241 + VP9MO0T/Q0pG/1VjW/9rdnD/iY2K/7Kwsf/Mycr/1tTV/9va2//d3d3/39/f/9zc3P/T09P/vr6+/5+f + n/97e3v/Wltb/0RERP86Ozv/ODg4/zs7O/88PDz/Ojo6/zc3N/8yMjL/LS0t/ycnJ/8eHh//FhYX/xUV + Ff8eHR3/MzIx/05MSv9jYV7/d3Rx/3d2c/9ubGr/VFNS/1hXV/8zMzP/Li4u/zk6Ov9ISUn/W1tb/zw8 + PP86Ojr/ODg4/zw8PP9CQkH/PDw8/z09Pf87Ozv/NzY2/zExMf8uLi7/Ly8v/zY2Nv9BQUH/T09P/1xc + XP9mZmb/bGxs/21tbf9ra2v/ampq/2hoaP9nZ2f/Z2dn/2dnZ/9nZ2f/ZmZm/2tra/9fX1//Ly8v/zEx + Mf8xMTH/MTEx/zIyMv8xMTH/MjIy/zIyMv8yMjL/MzMz/zIyMv8yMjL/MjIy/zIyMv8yMjL/MjMy/y8u + MP9NU0D/VF1E/0FFOP8wMS//KSkr/yYlKf8rKyv/LCws/ywsLP8rKyv/LCws/09PT/9hYmP/t7u8/8bL + yf9zdnb/nhJW/6oATv+mAU7/pQBM/6QAS/+hAEj/ogBJ/6MASv+lAEz/pgBN/6cATv+oAFD/qQBR/6oA + Uv+sAFT/rQBV/64AVv+vAFj/sQBZ/7IAWv+zAVz/tAJe/7UDYP+3A2H/tQBd/74AX/+ZY4L/aH9y/5OU + kv+2tLT/uLa3/8PBwv/U09T/3d3d/9/f3//c3dz/z8/P/7i4uP+VlZX/cnNz/1RVVf9BQUH/OTk5/zk5 + Of87Ozv/Ojo6/zk5Of81NTX/MTAw/ysrK/8kJCT/HB0d/xUWFv8WFhb/ISAg/zY1NP9TUU//bWto/3t5 + dv94dXP/bWtq/3Bvbv9qamr/WFlZ/yMjJP8kJCT/SEhI/2BgYP9eXl7/YmNi/15eXv9tbW3/Tk5O/zs7 + O/8+Pj7/Ojo6/zU1Nf8yMjL/Ly8v/zExMf84ODj/RERE/1FRUf9eXl7/aGho/2xsbP9tbW3/a2tr/2lp + af9nZ2f/Z2dn/2dnZ/9nZ2f/aGho/2dnZ/9nZ2f/Z2dn/2dnZ/9mZmb/ZmZm/21tbf8+Pj7/Li4u/zIy + Mv8xMTH/MTEx/zExMf8yMjL/MTEx/zIyMv8yMjL/MjIy/zIyMv8yMjL/MTEx/zIxMf8yMTH/MTEx/zAv + MP8tLC//LSwv/y4uLv8uLi7/LS0s/ywsLP8sLCz/LCws/ywsLP8qKir/Nzg4/1paWv+Iioz/0tTU/5Wk + nf+CK1f/rgBP/6QBTf+lAEz/owBK/6EAR/+iAEj/owBK/6QAS/+lAEz/pwBO/6gAT/+pAFH/qgBS/6sA + U/+sAFT/rQBW/68BWP+wA1r/sQJb/7IAWv+yAFf/swBW/7UAWf+6F2n/wHWd/8LGxP/SztD/xsbH/66v + r/+5ubn/1NTT/8vLy/+xsbH/j4+P/25ubv9QUFD/QEBA/zo6Ov85OTn/Ozs7/zs7O/84ODj/NDQ0/y8v + L/8oKCj/ISEh/xobG/8VFRX/FxcX/yUkJP87Ojn/VlRS/29sav94dnP/d3Vy/2RiYf9IR0f/NjY2/ysr + K/86Ojr/RUVG/zExMf9jY2P/UlJS/0dHR/9LS0r/Tk5O/1laWf9OTk7/R0dH/zk6Of8zMzP/MTEx/y8v + L/8yMjL/Ojo6/0ZGRv9UVFT/YGFg/2lpaf9tbW3/bW1t/2tra/9oaGj/Z2dn/2dnZ/9mZmb/ZmZm/2Zm + Zv9nZ2f/Z2dn/2ZmZv9nZ2f/ZmZm/2ZmZv9mZmb/ZmZm/2ZmZv9lZGX/bGxs/1ZWVv8tLS3/MjIy/zEx + Mf8xMTH/MjIy/zExMf8xMTH/MTEx/zExMf8xMTH/MjIy/zExMf8zMzP/NDQ0/zM0NP8zMzP/MjIy/zEx + Mf8xMTH/Ly8v/y4uLv8tLS3/LCws/ywsLP8tLS3/LCws/y0tLf8pKSn/S0tL/2doaf+4urz/vcjD/3pZ + a/+pAk//pQFM/6QAS/+jAEr/oABH/6EASP+iAEn/pABK/6UATP+mAE3/pwBO/6gAUP+pAFH/qwBT/6wA + VP+tAlf/rQBU/64AUP+wAFT/swle/7cpcf+8Vor/wYel/8W9wf/T3dj/3t7d/9nZ2f/Gxsb/ra6u/4+P + j/9oaGj/TExM/z4+Pv85OTn/Ojo6/zw8O/86Ojr/Nzc3/zMzM/8uLi7/KCgo/yAgIf8YGBn/FRUV/x0d + Hf8tLCv/Pz48/1pYVv9ubGn/eXd0/3Fvbf9eXVv/SEdG/zQ0NP8uLi7/VlZW/0FBQf9OTk7/WFlY/2Rl + ZP9qa2r/NjY2/0RFRP9jY2P/UVFR/0ZGRv84ODj/MjIy/y0tLf8sLCz/MjIy/zw8PP9ISEj/VlZW/2Ji + Yv9qamn/bW1t/21tbf9ra2v/aGho/2dnZ/9mZmb/Z2dn/2dnZ/9mZmb/Z2dn/2ZmZv9lZmb/ZmZm/2Zm + Zv9mZmb/ZmZm/2ZmZv9lZWX/ZmZm/2ZmZv9lZWX/ZWVl/2VlZf9lZWX/aGho/zc3N/8vLy//MTEx/zEx + Mf8xMTH/MTEx/zExMf8yMjL/MTEx/zExMf8xMTH/MzMz/yoqKv8hISH/Hx8f/yAgIP8rKyv/MjMz/zAw + MP8vLy//LS0t/y0tLf8sLCz/LCws/ywsLP8sLCz/LCws/ysrKv8zMzT/W1tc/42Qkv/R19X/iIeJ/5kI + Tf+oAEv/owFL/6IASf+fAEb/oQBH/6IASf+jAEr/pABL/6UATP+nAE7/qABP/6kAUP+qAFL/qwBT/6sA + Tv+xF2L/t1WF/76Npf/Esrv/zM/O/9fj3P/c5+H/5efl/7m4uf+CgoL/ZWVl/0tLS/89PT3/Nzc3/zo6 + Ov88PDz/OTk5/zY2Nv8xMTH/LCws/yUlJf8eHh7/GBgY/xQUFP8aGRn/LCwr/0dFQ/9eXFr/aGZk/2Ni + YP9jYmH/VlVT/0JBQf8xMTH/Kioq/yoqKv8vLy//NjY1/zc3Nv9PT0//ZWVl/2BgYP9cXFz/VVVV/09P + T/89PT3/ODg4/y8vL/8sLCz/Li4u/zQ0NP8+Pj7/S0tL/1hYWP9iYmL/ampq/21tbf9sbGz/aWlp/2dn + Z/9mZmb/ZmZm/2ZmZv9nZ2f/Z2dn/2dnZ/9nZ2f/ZmZm/2dnZ/9mZmb/ZmZm/2ZmZv9mZmb/ZmZm/2Zm + Zv9mZmb/ZWVl/2VlZf9mZmb/ZWVl/2RkZP9kZGT/ZWVl/2NjY/9tbW3/Tk9O/y0sLf8yMjL/MTEx/zEx + Mf8xMTH/MTEx/zExMf8xMTH/MTEx/zMzM/8mJSX/ISAf/zo4N/8nJST/HBoZ/xcWFv8iISH/MTEx/zAw + MP8uLi7/LS0t/y0tLP8sLCz/LCws/ywsLP8sLCz/LCws/ykoKf9LTEz/cHFy/8THyP+ksav/jCBU/6oA + S/+iAUr/ogBI/58ARf+gAEf/oQBI/6MASf+kAEv/pQBM/6YATf+nAE7/qABQ/6kCUf+rAlH/uWWN/8K/ + wf/P29X/4evm/+zx7v/s6+v/4N7f/+Dd3v/X19f/UVJT/zIyMf85OTn/Ojo6/zk5Of81NDT/Ly8v/yoq + Kv8kJCT/HBwd/xUWFv8VFRX/IyIi/zQzMv9HRUT/YV9d/3Bua/9wbmz/ZWNh/0tKSf8zMjL/SklI/0FA + P/8kIyP/MTEx/zY2Nv86Ojr/PDw8/z09Pf89PT3/Pz8//zw8PP9JSUn/QkJC/zc3N/8wMDD/LS0s/zEx + Mf82Njb/QkJC/05OTv9bW1v/ZGRk/2pqav9ra2v/ampq/2hoaP9mZmb/ZWVl/2VlZf9mZmb/ZmZm/2Zm + Zv9mZmb/ZmZm/2ZmZv9mZmb/ZWVl/2VlZf9lZWX/ZmZm/2ZmZv9mZmb/ZmZm/2VlZf9mZmb/ZmZm/2Zm + Zv9mZmb/ZWVl/2VlZf9kZGT/ZGRk/2NjY/9kZGT/ZGRk/2ZmZv9kZGP/MjIy/zAwMP8xMTH/MTEx/zIy + Mv8xMTH/MTEx/zExMf8xMTH/Ly8v/yIiIv86OTj/QkE//0FAP/87Ojn/LCoq/xgXFv8nJif/KSkp/yws + LP8uLi7/LS0t/ywsLP8sLCz/Kysr/ywsLP8rLCz/Kikp/zY2Nv9hYmL/pKao/8DPyf+IQWT/pwBH/6IC + Sv+hAEj/ngBF/58ARv+hAEf/ogBJ/6MASv+kAEv/pQBN/6cATv+oA1H/pgBI/7xpkf/b7eT/6urp/+Th + 4v/GxMX/oJ6f/4B/f/9ra2v/qamo/5yfn/8vLy//MjEx/y4uLv8oKCj/ISEh/x4eHv8YGBj/GBgY/yMi + Iv82NTT/UE5M/2poZf9pZ2b/XFta/1taWf9FRUT/Pj49/0BAP/9FREP/Li4u/zIyMf9TUlD/UU9O/zY2 + Nv87Ozv/Pj4+/z8/P/8/Pz//Pj4+/zs7O/83Nzf/MzQz/y4uLv8wMDD/ODg4/0RERP9RUVH/W1tb/2Zm + Zv9ra2v/bGxs/2tra/9oaGj/ZmZm/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZmZm/2Vl + Zf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9mZmb/ZWVl/2VlZf9lZWX/ZWVl/2Vl + Zf9lZWX/ZWVl/2VlZP9jY2P/Y2Nj/2RkZP9kZGT/YmJi/2xsbP9FRUT/LS0t/zIyMv8xMTH/MTEx/zEx + Mf8xMTH/MTEx/zExMf8uLi7/MC8v/zk3Nv9PTk3/dnVy/0hHRf8zMTD/JSQk/yYmJv8uLi3/Kioq/yoq + Kv8uLi3/Ly8v/y4uLv8uLi7/LCws/ysrK/8sLCz/KSkp/1VWVv+LjI//ydbR/5Bief+iAEX/ogJK/6EA + R/+eAET/nwBF/6AAR/+hAEj/owBJ/6QASv+lAEz/pgFO/6YBS/+sFl3/39vc/9bX1v+hoKH/gIGB/3Nz + c/9/f37/lpaV/6mpqP+4ubn/VlhZ/x8fH/8lJSX/Ghoa/x0dHf8uLi7/NDMz/0lIR/9nZWP/bWtp/2Nh + YP9XVlX/QkFB/y0sLP89PDz/Q0FB/yknKP86Ojn/UlJQ/0lJSP87Ozv/Ojo5/z09PP8/Pz//PT09/z09 + Pf86Ojr/NjY2/zMzM/8xMTH/MzMz/zs7O/9GRkb/VFRU/19fX/9oaGf/bGxs/2tra/9paWn/aGho/2Zm + Zv9lZWX/ZmZm/2ZmZv9lZWX/ZmZm/2VlZf9kZGT/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2Vl + Zf9lZWX/ZWVl/2VlZf9mZmb/ZmZm/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2Rk + ZP9lZWX/ZGRk/2RkZP9kZGT/ZGRk/2NjY/9iYmL/aGho/1xdXP8wLy//MjIy/zExMf8xMTH/MTEx/zIy + Mv8xMTH/MTEx/y8vL/8yMjL/MC8v/0JBQP9UU1H/Q0JA/zMxMP8lJST/KSkp/zIyMv8vLy//Li4u/yQk + JP8gHx//Hx4e/yEhIf8uLy//LS0t/ywsLP8nJyf/QkJD/3t9f//CzMr/n4aS/50CRP+iAkn/oABH/50A + Q/+fAEX/oABG/6EAR/+iAEn/owBK/6QAS/+mBE//ogBC/8h3nf/S39n/kI2O/5WVlP+lpaP/tbOx/7u6 + uf+8u7n/vLq5/46Rkf8jJCT/FhUV/xcWFv87Ojj/W1lY/01NTP9KSUj/SUhH/zMzMv8vLy//LCws/yws + LP8wMDD/NjU1/0VDQv9JR0b/Ozo5/zg4OP86Ojr/Ojo7/z09Pf88PDz/ODk4/zQ0NP8xMTH/MTEx/zU1 + Nf8+Pj7/SkpK/1dXV/9iYmL/aWlp/2xsbP9ra2v/aWlp/2dnZ/9lZWX/ZWVl/2VlZv9mZmb/ZmZm/2Vl + Zf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9kZGT/ZGRk/2Vl + Zf9kZGT/ZWVl/2VlZf9lZWX/ZGRk/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZGRk/2VlZf9lZWX/ZWVl/2Vl + Zf9kZGT/ZGRk/2RkZP9kZGT/Y2Nj/2NjY/9jY2P/aWlp/zw8PP8vLy//MjIy/zExMf8xMTH/MTEx/zIy + Mv8vLy//Li4u/zIyMf8xMTD/MjEx/y4tLf8sKyv/Li4t/yoqKv8vLy//Ly8v/zAwMP8jIyP/MC8u/y4s + K/8WFBT/GxoZ/xsaGv8rKyv/LS0t/yoqKv8xMTH/amts/7S7uv+yq7H/mgRJ/6IAR/+fAUb/nQBD/54A + RP+fAEX/oABH/6EASP+iAEn/pAFL/6UBS/+lBk3/2sbQ/42Skf93dHP/r62s/7e2tP+1s7L/oqGg/4WE + hP9vcHD/SEpL/xoZGf8gHx//JiQk/zQzM/81NDP/NjU1/z8+Pf9OTEv/Q0JB/ywrK/84ODf/PT09/zw8 + PP87Ozv/PDw7/z4+Pv89PT3/Ozs7/zg4OP80NDT/MTEx/zExMf83Nzb/QUFB/01NTf9aWlr/ZGRk/2tr + a/9sbGz/a2tr/2lpaf9nZ2f/ZWVl/2ZmZv9mZmb/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2Vl + Zf9lZWX/ZWVl/2VlZf9mZmb/ZWVl/2RkZP9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2Rk + ZP9kZGT/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2RkZP9lZWX/ZGRk/2RkZP9lZWX/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2NjY/9qamr/VVVU/y0tLf8yMjL/MTEx/zExMf8yMjL/MDAw/yws + LP8yMjL/MDAw/zExMf8xMTH/MTIx/zEyMf8xMTH/MTEx/zAwMP8wMDD/KSkp/ycmJv9APj3/RUNC/0hG + Q/81MzP/LCoq/xoZGf8sLCz/LCws/ygoKP9bXF3/qrGx/7eutP+WAEL/ogBH/58ARv+cAEL/nQBD/54A + Rf+fAEb/oQBH/6IASf+kA0z/oABB/7pKfv/i7Of/t7S0/6alpP+WlZT/f39+/2VlZf9KSkr/QkJC/1BR + UP83Nzf/Ly8v/zQ1NP82Nzb/MDAw/0dFRP9fXlz/W1lY/19dW/9TUlH/Pj09/zo6Ov8+Pj7/PDw8/zs7 + Ov83Nzf/MjIy/zExMf8zMzP/ODg4/0NDQ/9QUFD/XV1d/2ZnZv9sbGz/bGxs/2pqav9oaGj/Z2dn/2Zm + Zv9lZWX/ZmZm/2ZmZv9mZmb/ZWVl/2VlZf9mZmb/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2Vl + Zf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZmZm/2VlZf9lZWX/ZGRk/2Vl + Zf9lZWX/ZWVl/2RkZP9lZWX/ZWVl/2VlZf9kZGT/ZWVl/2VlZf9kZGT/ZWVl/2RkZP9lZWX/ZWVl/2Rk + ZP9lZWX/ZGRk/2RkZP9kZGT/ZGRk/2VlZf9oaGf/Nzc2/y8vL/8xMTH/MTEx/zMzM/8sLCz/LCwr/zAw + MP8xMTH/MjIy/zExMf8yMjL/MTEx/zExMf8xMTH/MDAw/y8vL/8qKir/MTAw/0RCQf9WVFH/RUNC/1JQ + Tf8zMjL/IB8e/yYmJv8uLi7/JiYm/0lKS/+fpqb/w7q//54HSf+gAEX/ngFF/5wAQf+dAEP/ngBE/58A + Rf+gAEf/oQBI/6MDS/+hAEH/woSh/56qo/+Cfn7/TExM/xQUFP8UFBT/IyQj/ygoKP9IR0f/UVJS/zc3 + N/88PDz/Ozs7/zw9PP87Ozr/RUND/0lIR/9AQD//Ozs7/zo6Ov86Ojr/NjY2/zIyMv8xMTH/NDQ0/zw8 + PP9HR0f/U1NT/2BgX/9nZ2f/a2tr/2xsbP9qamr/aWlp/2ZmZv9mZmb/ZmZm/2ZmZv9lZWX/ZmZm/2Vl + Zf9mZmb/ZGRk/2VlZf9lZWX/ZGRk/2VlZf9kZGT/ZWVl/2RkZP9lZWX/ZWVl/2RkZP9kZGT/ZmZm/2Rk + ZP9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9kZGT/ZWVl/2VlZf9lZWX/ZWVl/2RkZP9kZGT/ZWVl/2Vl + Zf9kZGT/ZGRk/2VlZf9lZWX/ZGRk/2VlZf9kZGT/ZGRk/2VlZf9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2VlZf9kZGT/YmJi/2pqav9NTUz/LCws/zExMf8yMjL/Kioq/xkYGP8eHRz/GBYW/xkY + GP8sLCz/MjIy/zAwMP8xMTH/MTEx/zExMf8wMDD/Ly8v/y4uLv8xMDD/Ozk5/1VTUf9XVVP/RkRC/y8u + Lv8kIyP/KCgo/ysrK/8mJib/Ozs8/5Sbm//Kwcf/ow1P/54AQ/+eAUT/mwBA/5wAQv+dAEP/ngBF/58A + Rv+hAUf/nwBF/64OVv+ciZP/Oj48/1FOTv9IR0f/Ly4u/yYmJv8kJCT/Jycm/zIyMv8+Pj7/Pz8//0BA + QP9CQkL/QkJC/0FBQf88PDz/Ozs7/zk5Of82Njb/MzMz/zY2Nf8/Pz//S0tL/1hYWP9iYmL/aWlp/2xs + bP9ra2v/aWlp/2dnZ/9mZmb/ZmZm/2ZmZv9mZmb/ZmZm/2ZmZv9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2Rk + ZP9kZGT/ZWVl/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9lZWX/ZGRk/2RkZP9kZGT/ZWVl/2Rk + ZP9lZWX/ZWVl/2VlZf9kZGT/ZWVl/2RkZP9lZWX/ZWVl/2VlZf9lZWX/ZGRk/2VlZf9lZWX/ZWVl/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2VlZf9kZGT/ZWVl/2VlZf9lZWX/ZGRk/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/Z2dn/2FhYf8xMTD/MDAw/y4uLv8aGRn/MzAw/0xJSP8sKin/FhQU/xYV + Ff8tLS3/MjIy/zExMf8xMTH/MTEx/zAwMP8vLy//Li4u/zIzMv8wLy//MzEx/zg3Nv8sLCz/Ly8v/ycn + J/8sLCz/Kioq/ycnJv8xMDH/iI+P/8e/xf+jDk//nQBC/50BRP+aAED/mwBB/5wAQv+dAET/nwBF/6AC + R/+dAED/sy5q/3F0dP82Njb/Ojo6/zk5Of85OTn/ODg4/z08PP9AQED/P0BA/z09Pf89PT3/Ozs6/y4u + Lf8hICD/ISEh/zQ0NP8zMzL/MTEx/y8vL/9NTU3/aGho/2tra/9tbW3/a2tr/2hoaP9mZmb/ZWVl/2Vl + Zf9lZWX/ZWVl/2ZmZv9mZmb/ZmZm/2ZmZv9lZWX/ZGRk/2VlZf9lZWX/ZWVl/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9lZWX/ZGRk/2VlZf9kZGT/ZGRk/2VlZf9kZGT/ZWVl/2Vl + Zf9lZWX/ZWVl/2VlZf9lZWX/ZGRk/2RkZP9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9kZGT/ZWVl/2Rk + ZP9kZGT/ZGRk/2VlZf9lZWX/ZWVl/2RkZP9kZGT/ZWVl/2RkZP9kZGT/ZWVl/2RkZP9kZGT/ZGRk/2Rk + ZP9jY2P/ZWVl/2VlZf9kZGT/ampq/0NDQ/8uLS7/JCQk/y4sLP9EQkH/T01L/1VTUP84NjX/IB4e/yAg + IP8zMzP/MTEx/zExMf8yMjL/MTEx/y8vL/8tLS3/Li4u/zExMf8vLy//Li4u/zExMf8vLy//LCws/yws + LP8qKir/KCgo/yopKv98g4T/xr7F/6MOT/+cAEH/nQFD/5oAP/+bAED/nABC/50AQ/+eAET/nwJG/6IA + Qv+cMmP/ND87/yooKP8uLi7/Li4u/y8vL/8xMTH/MjIy/zU1Nf82Njb/NTU1/zIyMv8vLy//BwYG/wYG + Bv8WFhb/MDAw/zIyMv8zMzP/Ly8v/0JCQf9oaGj/Z2dn/2ZmZv9mZmb/ZWVl/2VlZf9mZmb/ZmZm/2Vl + Zf9mZmb/ZmZm/2ZmZv9lZWX/ZWVl/2RkZP9kZGT/ZWVl/2RkZP9lZWX/ZGRk/2NjY/9lZWX/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZWVl/2RkZP9kZGT/ZGRk/2RkZP9lZWX/ZGRk/2Rk + ZP9lZWX/ZWVl/2VlZf9kZGT/ZWVl/2RkZP9kZGT/ZGRk/2RkZP9lZWX/ZWVl/2RkZP9lZWX/ZGRk/2Rk + ZP9kZGT/ZWVl/2RkZP9kZGT/Y2Nj/2VlZf9kZGT/ZGRk/2VlZf9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9naGj/XV1d/y8vLv8qKir/MjEw/0RCQf9bWVb/VlRS/1FPTP8pKSn/ISEg/zIy + Mv8xMTH/MTEx/zExMf8yMjL/MTEy/zAwMP8tLS3/LCws/y0tLf8uLi7/Li4u/ysrK/8sLCz/LCws/ykp + Kf8qKir/Jycn/3R7e//Kw8r/pA9P/5sAQP+cAUL/mQA+/5oAQP+bAEH/nABC/50AQ/+dAUX/pgBG/4U8 + Xv8pNDD/MC0u/zAwMP8xMTH/MTEx/zExMf8yMjL/KSkp/yMjI/8oKCj/MTEw/zU1Nf8uLi7/NTQ0/zY2 + Nv8yMjL/MjIy/zIyMv8xMTH/MjEx/1hYWP9paWn/ZmZm/2VlZf9lZWX/ZmZm/2ZmZv9mZmb/ZWVl/2Vl + Zf9lZWX/ZGRk/2VlZf9kZGT/ZGRk/2VlZf9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2VlZf9kZGT/ZGRk/2VlZf9kZGT/ZWVl/2Vl + Zf9lZWX/ZGRk/2VlZf9kZGT/ZWVl/2RkZP9kZGT/ZGRk/2RkZP9lZWX/Y2Nj/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9lZWX/ZWVl/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2NjY/9paWn/PDw7/y0tLf81NTT/MzEw/1BOS/9QTUv/Pjw7/ykoKP8jIyP/MzMz/zEx + Mf8yMjL/Ly8v/yorK/8nJyf/JiYn/ysrLP8vLy//LS0t/ywsLP8tLS3/LCws/ywsLP8rKyv/KSkp/ysr + K/8oJib/cHt7/8OpuP+eA0L/nAFC/5sAQf+YAD7/mQA//5oAQP+cAEH/nQBD/5wBQ/+nAkj/cDpT/ycx + Lf8wLi//MDAw/zExMf8yMjH/MTEx/yEgIP8dGxv/Jycm/yYmJv8aGhr/IyMi/zQ0NP8wMDD/MDAw/zEx + Mf8yMjL/MjIy/zIyMv8vLy//Q0ND/2dnZ/9mZmb/ZWVl/2RkZP9lZWX/ZmZm/2VlZf9lZWX/ZWVl/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Vl + Zf9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2Rk + ZP9kZGT/ZWVl/2RkZP9kZGT/ZGRk/2RkZP9lZWX/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9lZWX/ZWVl/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2VlZf9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/Y2Nj/2lpaf9VVVT/LCws/zQ1Nf84ODf/NDMz/zEwMP8xMDD/Kikp/y8vL/8zMzP/MjIy/ysr + K/8iISH/QUA//yonJv8YFhb/HRwc/yUlJf8uLi7/Kysr/ywsLP8sLCz/LCws/ysrK/8pKSn/Kysr/ycl + Jv9yfn7/x6O1/5sAPf+bAUL/mgBA/5gAPf+ZAD7/mgA//5sAQP+cAEL/nABC/6QBSP9bOEn/JCwo/y4s + Lf8sLCz/MDAw/zIyMv8uLi3/MjIx/0A/Pv9JSEb/RkZF/y8vLv8PDg7/ISAg/zQ0NP8xMTH/MTEx/zEx + Mf8xMTH/MTEx/zExMf8zMzL/WlpZ/2hoaP9lZWX/ZmZm/2ZlZf9lZWX/ZWVl/2VlZf9lZWX/ZGRk/2Vl + Zf9kZGT/ZGRk/2NjY/9kZGT/Y2Nj/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Vl + Zf9kZGT/ZWVl/2RkZP9lZWX/ZGRk/2VlZf9kZGT/ZGRk/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2Vl + Zf9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2VlZf9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9lZWX/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9jY2P/Y2Nj/2VlZf9kZGT/Y2Nj/2Nj + Y/9kZGT/ZWVl/2ZmZv81NTX/Ly8v/zQ0NP87Ozv/ODg3/zExMf8wMDD/NDQ0/zIyMv8xMTH/JCQk/zU0 + M/9DQUD/QD8+/z48PP8xMDD/HRwc/yUlJf8tLS3/LCws/ysrK/8rKyv/Kysr/ygoKP8rLCz/JSMk/3mI + hv/DhqL/mAA3/5sDQv+aAD//lwA8/5gAPf+ZAD//mgBA/5sAQf+bAEH/owJH/1IwP/8xOTX/PDo6/0FB + QP82NjX/MjIy/zw8O/8/Pz7/Ozo6/zs7Of85ODf/NzY1/y0tLP8UExP/LCsr/zMzNP8yMjL/MTEx/zEx + Mf8xMTH/MTEx/y4uLv9EREP/aGhn/2dnZ/9mZmb/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9kZGT/ZWVl/2Nj + Y/9jY2P/Y2Nj/2RkZP9jY2P/Y2Nj/2NjY/9kZGT/ZGRk/2VlZf9kZGT/ZGRk/2VlZf9lZWX/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9lZWX/ZWVl/2RkZP9kZGT/ZGRk/2VlZf9kZGT/ZGRk/2RkZP9kZGT/ZWVl/2Rk + ZP9lZWX/ZGRk/2RkZP9kZGT/ZWVl/2VlZf9lZWX/ZWVl/2RkZP9kZGT/ZGRk/2RkZP9lZWX/ZWVl/2Vl + Zf9lZWX/ZGRk/2RkZP9lZWX/ZGRk/2RkZP9kZGT/ZGRk/2NjY/9lZWX/ZGRk/2NjY/9kZGT/ZGRk/2Rk + ZP9kZGT/a2tr/0tLS/8sLCz/MTEx/zAwMP8xMTH/MjIy/y4uLv8rKyv/Ly8v/y8vL/8uLi7/NzU1/01M + S/9dXFr/UVBN/zAvLv8sKyv/IiEi/y8vL/8sLCz/LCws/ywsLP8rKyv/KCgo/ywsLP8nJCX/dYSC/7Zf + hv+XADb/mwNC/5kAP/+WADv/lwA8/5gAPv+ZAD//mgFB/5oAPv+kD0//V0tS/zw/Pf84Nzf/VlVT/1lZ + V/8wMDD/QkFA/0FBQP86OTn/ODc2/zw8O/88PDv/ODc2/yYmJf8hICD/NDQ0/zExMf8xMjH/MTEx/zEx + Mf8xMTH/MDAw/zQ0NP9dXVz/aWlp/2ZmZv9mZmb/ZmZm/2VlZf9kZGT/ZGRk/2RkZP9jY2P/ZGRk/2Nj + Y/9kZGT/ZGRk/2RkZP9jY2P/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZWVl/2VlZf9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZWVl/2VlZf9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9jY2P/ZGRk/2Vl + Zf9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9jY2P/Y2Nj/2NjY/9kZGT/ZWVl/2Vl + Zf9nZ2f/YmJi/zExMf8wMDD/MjIy/zIyMv8yMjL/MzMz/zAwMP8sLCz/LCws/zAvL/80MjL/NDIy/09N + TP9CQD7/Liws/yoqKv8mJib/Li4u/ywsLP8sLCz/LCws/ysrK/8oKCj/LCws/ygnJ/9/hof/rjZq/5YA + N/+aAkD/mAA+/5UAOv+XADz/mAA9/5kAPv+aAD//mwA//5sIR/9LP0b/MTQz/zMyM/8xMTH/Nzc3/zEx + Mf9AQD//QkJB/0JCQf8+PTz/ODc3/zs6Of87Ojn/MDAv/ycnJv8zMzP/MTEx/zExMf8xMTH/MTEx/zEx + Mf8xMTH/Li4u/0hIR/9oaGj/ZmZm/2ZmZv9lZWX/ZWVl/2RkZP9kZGT/Y2Nj/2RkZP9jY2P/ZGRk/2Nj + Y/9jY2P/ZGRk/2VlZf9kZGT/Y2Nj/2NjY/9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZWVl/2VlZf9kZGT/ZGRk/2Rk + ZP9kZGT/ZWVl/2RkZP9kZGT/ZWVl/2VlZf9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9jY2P/ZGRk/2Rk + ZP9kZGT/Y2Nj/2RkZP9lZWX/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9jY2P/ZGRk/2RkZP9kZGT/ZWVl/2Vk + Zf9qamr/QkJC/y0tLf8xMTH/MTEx/zIyMv8yMjL/MzMz/zMzM/8xMDD/MjIy/zU1Nf8zMjL/Ly4u/zEv + L/8xMDD/KCgo/ywsLP8tLS3/LCws/y0tLf8sLCz/Kysr/ygoKP8tLCz/LDEv/56Wnv+mEE//lwA8/5kB + P/+YAD3/lQA6/5YAO/+XADz/mAA9/5kBP/+aAD3/nQxK/1FITf8zNTT/PDw8/zc3N/8vLy//MDAw/zg4 + OP9EREP/QUFA/z8+Pf83Njb/NTQ0/zU0M/8xMTD/Ly8v/zIyMv8xMTH/MTEx/zExMf8xMTH/MTEx/zEx + Mf8vLy//NTU1/15eXf9oaGj/ZmZm/2VlZf9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/Y2Nj/2RkZP9kZGT/ZGRk/2NjY/9kZGT/ZWVl/2NjY/9kZGT/ZWVl/2Rk + ZP9kZGT/ZWVl/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZWVl/2RkZP9lZWX/ZWVl/2VlZf9lZWX/ZGRk/2Vl + Zf9kZGT/ZGRk/2RkZP9lZWX/ZGRk/2NjY/9jY2P/ZGRk/2VlZf9kZGT/ZGRk/2RkZP9jY2P/ZGRk/2Rk + ZP9kZGT/Y2Nj/2NjY/9kZGT/ZGRk/2NjY/9jY2P/Y2Nj/2RkZP9kZGT/Y2Nj/2RkZP9lZWX/ZWVl/2lp + af9aWlr/Li4u/zIyMv8xMTH/MTEx/zIyMv8yMjL/MTEx/zExMf8wMDD/MjIy/zQ0NP8+Pj3/Q0RD/zIy + Mv8tLS3/Li4u/y0tLf8tLS3/LCws/ywsLP8rKyv/KSkp/yspKv84QkD/oE5z/5sAO/+YAj//mAA9/5cA + PP+UADn/lQA6/5YAO/+XADz/mAA+/5cAPP+kDEv/c15p/y0yMP87OTr/Ozs7/zM0NP8uLi7/Ly8v/zo6 + Of9DQkL/Ojk4/zc2Nv82NTT/MjIx/zAwMP8xMTH/MjIy/zExMf8xMTH/MTEx/zExMf8xMTH/MTEx/zEx + Mf8uLi7/SUlI/2lpaf9mZmb/ZWVl/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2NjY/9kZGT/ZGRk/2Nj + Y/9jY2P/Y2Nj/2RkZP9kZGT/Y2Nj/2RkZP9jY2P/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Vl + Zf9lZWX/ZWVl/2VlZf9lZWX/ZGRk/2VlZf9lZWX/ZGRk/2VlZf9kZGT/ZWVl/2RkZP9lZWX/ZWVl/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Nj + Y/9kZGT/Y2Nj/2RkZP9kZGT/Y2Nj/2NjY/9jY2P/ZGRk/2RkZP9jY2P/Y2Nj/2RkZP9kZGT/ZWVl/2ho + aP88PDv/Li4u/zIyMv8yMjL/MjIy/zIyMv8xMTH/MTEx/zExMf8wMDD/Ly8v/zAwMP8vLy//Li4u/y0t + Lf8tLS3/LCws/y0tLf8tLS3/LCws/yoqKv8qKSr/Jyko/1BKT/+gEU7/lwA7/5gBPv+XADz/lgA7/5MA + OP+UADn/lQA6/5YAO/+YAD3/lwA9/6ABQv91VGT/OkE+/zs5Ov9EREP/X15c/0dHRv8wMDD/Ly8v/zQ0 + M/84ODf/NjU1/zMzM/8zMzL/MjIy/zExMf8xMTH/MTEx/zIyMv8yMjL/MjIy/zExMf8xMTH/MTEx/zAw + MP82Njb/YGBf/2hoaP9lZWX/ZGRk/2RkZP9kZGT/ZGRk/2VlZf9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2NjY/9jY2P/ZGRk/2RkZP9kZGT/ZWVl/2VlZf9kZGT/ZWVl/2RkZP9kZGT/ZWVl/2Rk + ZP9kZGT/ZWVl/2RkZP9kZGT/ZGRk/2VlZf9lZWX/ZWVl/2RkZP9kZGT/ZWVl/2VlZf9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZWVl/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2NjY/9kZGT/Y2Nj/2Rk + ZP9jY2P/Y2Nj/2RkZP9jY2P/ZGRk/2NjY/9kZGT/ZGRk/2NjY/9kZGT/ZGRk/2RkZP9kZGT/aWlp/1BR + UP8sLCz/MjIy/zExMf8xMTH/MTEx/zIyMv8xMTH/MTEx/zAwMP8wMDD/Ly8v/y8vL/8uLi7/LS0t/y0t + Lf8sLCz/LCws/ywsLP8sLCz/KSkp/yooKf8nMCz/ajxR/6ACQv+XAT3/lwA9/5YAO/+VADr/kwA3/5QA + OP+UADn/lgA6/5cAPP+WADz/oAJB/2Y5Tf9CS0b/Pj09/0ZGRf9hYF3/S0tK/zs7O/81NTX/MDAw/zEw + Mf8zMzP/NTU1/zU1Nf80NDT/NDQ0/zIyMv8wMDD/MDAw/zExMf8xMTH/MTEx/zExMf8xMTH/MTEx/y8v + L/9NTUz/aGho/2VlZf9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2VlZf9lZWX/ZGRk/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZWVl/2VlZf9lZWX/ZWVl/2RkZP9lZWX/ZWVl/2Vl + Zf9kZGT/ZWVl/2VlZf9lZWX/ZWVl/2RkZP9lZWX/ZGRk/2RkZP9lZWX/ZGRk/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9lZWX/ZGRk/2RkZP9kZGT/Y2Nj/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Nj + Y/9kZGT/Y2Nj/2NjY/9kZGT/ZGRk/2RkZP9jY2P/Y2Nj/2RkZP9kZGT/ZGRk/2RkZP9lZWX/YmJi/zU1 + Nf8vLy//MTEx/zExMf8xMTH/MTEx/zExMf8wMDD/MDAw/zAwMP8vLy//Ly8v/y4uLv8rKyv/Jygo/y0t + Lf8sLCz/LCws/ysrK/8pKSn/KSco/y03M/+EJE3/nAA8/5YBPf+WADz/lQA7/5QAOf+SADb/kwA3/5QA + OP+VADr/lgA7/5YBPP+eADz/dy9O/y86Nv84Njb/ODk5/zc3N/86Ojr/Pj4+/z4+Pv85OTn/NTU1/zY2 + Nv8xMTH/KSkp/yMjI/8jIyP/KCgo/zk5OP84ODj/MzMz/zExMf8yMjL/MTEx/zExMf8xMTH/Ly8v/zk5 + OP9iYmH/ZmZm/2VlZf9kZGT/Y2Nj/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZWVl/2VlZf9lZWX/ZGRk/2RkZP9kZGT/ZGRk/2Rk + ZP9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2RkZP9kZGT/ZWVl/2RkZP9kZGT/ZWVl/2RkZP9kZGT/ZGRk/2Vl + Zf9lZWX/ZGRk/2RkZP9lZWX/ZGVk/2RkZP9kZGT/ZGRk/2VlZf9kZGT/ZWVl/2RkZP9kZGT/Y2Nj/2Rk + ZP9kZGT/Y2Nj/2RkZP9kZGT/ZGRk/2NjY/9jY2P/ZGRk/2NjY/9kZGT/ZGRk/2NjY/9paWn/SEhI/y0t + Lf8yMjL/MTEx/zExMf8xMTH/MTEx/zIyMv8wMC//Li4u/ywsLP8qKir/JiYm/zExMP9AQD//KCgo/ysr + K/8tLS3/LS0t/yopKf8aGxr/RUNG/5sQSv+XADr/lgE8/5YAO/+VADr/lAA4/5EANf+SADb/kwA4/5QA + Of+VADr/lQI8/5oAOf+MKVL/OUNA/zc0Nf87Ozv/PT09/z4+Pv88PDz/Pj4+/0BAQP87Ozv/IyIi/xgX + Fv8XFRT/Hx0c/yclJP8aGRn/KSkp/zk4OP81NTX/Ly8u/zAwMP8yMjL/MTEx/zAwMP8wMDD/Li4u/09P + Tv9nZ2f/ZGRk/2RkZP9kZGT/Y2Nj/2RkZP9jY2P/ZGRk/2NjY/9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZWVl/2VlZf9lZWX/ZWVl/2RkZP9lZWX/ZGRk/2RkZP9kZGT/ZWVl/2Rk + ZP9kZGT/ZWVl/2VlZf9lZWX/ZWVl/2RkZP9kZGT/ZWVl/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Rk + ZP9lZWX/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9jY2P/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9jY2P/ZGRk/2Rk + ZP9kZGT/Y2Nj/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2VlZf9dXV3/MTEw/zEx + Mf8xMTH/MTEx/y8vL/8tLS3/Kysr/zAwMP8xMTH/Nzc3/0FBQP9bW1j/OTk5/4iGgv9TU1D/Li4u/yMi + Iv8bGxv/JCEi/05ZVv+PQ2b/mwE7/5YBPP+WADv/lQA6/5QAOf+TADj/kAA0/5EANv+SADf/kwA4/5QA + Of+VATv/lgA4/5oYTf9LS07/MjMy/zo6Ov87Ozv/PDw8/z09Pf8/Pz//OTk4/zExMf8iIiH/LSsq/zMx + MP9OTEr/SUdG/yYkJP8ZGRj/MDAw/y8vL/8vLy//Ly8v/y8vLv8wMDD/MTEx/zAwMP8uLi7/Ojo5/2Ji + Yv9mZmb/ZGRk/2RkZP9kZGT/Y2Nj/2RkZP9jY2P/Y2Nj/2RkZP9jY2P/ZGRk/2RkZP9jY2P/Y2Nj/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2VlZf9lZWX/ZGRk/2VlZf9lZWX/ZGRk/2RkZP9lZWX/ZGRk/2Rk + ZP9lZWX/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2VlZf9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Vl + Zf9kZGT/ZGRk/2RkZP9kZGT/ZWVl/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Rk + ZP9jY2P/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/Y2Nj/2hoaP9AQED/Li4u/zEx + Mf8xMTH/NTY2/0JCQf9GRkX/WVhW/1taWP9qaWb/e3p2/2poZf9GRkT/ODc1/yUlJP8pKSr/TU1O/4eE + h/+9xsT/z7vG/58MRP+VATn/lgE8/5UAOv+UADn/kwA4/5IAN/+PADP/kAA0/5IANv+SADf/kwA4/5QA + Of+TADj/ngZD/25VYv8vNTP/Ojk5/zo6Ov88PDz/Pj4+/zo6Ov83Nzb/Pz8//z4+Pv9BPz//TEpI/2Bf + Xf9PTkz/OTc3/xkYGP8pKCj/MjMz/zIyMv8zMzP/MDAw/zExMf8vLy//MTEx/zAwMP8vLy7/UlJR/2ho + aP9kZGT/ZGRk/2NjY/9kZGT/Y2Nj/2JiYv9jY2P/Y2Nj/2NjY/9kZGT/Y2Nj/2NjY/9kZGT/ZGRk/2Nj + Y/9jY2P/ZGRk/2RkZP9kZGT/ZGRk/2VlZf9lZWX/ZWVl/2RkZP9kZGT/ZGRk/2VlZf9lZWX/ZWVl/2Rk + ZP9lZWX/ZWVl/2VlZf9kZGT/ZGRk/2RkZP9kZGT/ZWVl/2RkZP9kZGT/Y2Nj/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9jY2P/Y2Nj/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/Y2Nj/2RkZP9kZGT/ZGRk/2RkZP9lZWX/ZGRk/2RkZP9jY2P/aWlp/1dXV/8uLi7/MjIy/yws + Lf9ZWVj/iomE/3Bva/9cWlj/VFNR/0hHRf8wLy7/GhkZ/ykoKv9KSUz/hIOF/7/Bwv/g6Of/5PLu/8vJ + zP+hKVn/lAA1/5cCPf+VADr/lAA5/5MAOP+SADf/kQA1/44AM/+PADT/kQA1/5IANv+SADf/kwA4/5QC + Ov+YADb/jURi/zhEQP83NDX/Ojs6/zw8PP89PT3/Nzc2/z4+Pv8+Pj7/PT09/zw6Ov9FQ0H/RkRD/0JA + P/9CQD//KSgo/yQkJP85OTn/LCwr/x0cG/8eHRz/KCcm/yEhIP8tLS3/MjIy/y4uLv88PTz/Y2Nj/2Vl + Zf9kZGP/ZGRk/2RkZP9jY2P/Y2Nj/2NjY/9jY2P/Y2Nj/2NjY/9jY2P/Y2Nj/2RkZP9kZGT/Y2Nj/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2VlZf9lZWX/ZWVl/2Rk + ZP9lZWX/ZWVl/2RkZP9lZWX/ZGRk/2VlZf9kZGT/ZGRk/2VlZf9kZGT/ZGRk/2VlZf9kZGT/ZGRk/2Vl + Zf9lZWX/ZGRk/2VlZf9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/Y2Nj/2Nj + Y/9kZGT/ZGRk/2NjY/9lZWX/ZWVl/2VlZf9lZWX/ZGRk/2RkZP9mZmb/aGho/zo6Ov8vLy//Ly8v/z49 + Pf9UU1H/ODc3/ywsLP8tLS3/JCIj/0VGR/93fHv/m6Sh/7LAu//K19b/ycvO/7ehrf+pboj/nBpO/5UA + Nv+XAT3/lQA6/5QAOf+TADj/kgA3/5EANv+QADX/jgAy/44AM/+QADT/kQA1/5IANv+TADf/kwE5/5QA + NP+aIVH/TlNT/zIyMf86Ojr/PDw8/zs7O/85ODj/QUBA/0FAQP9BQUH/PDw7/z08O/8/PTz/QT8+/0NB + QP8kJCP/Li4u/y4uLv8dGxv/IyEg/yonJ/8sKin/GxoZ/yUlJf8xMTH/MDAw/y8vL/9UVFP/Z2hn/2Rk + ZP9kZGT/ZGRk/2NjY/9jY2P/ZGRk/2RkZP9jY2P/ZGRk/2RkZP9kZGT/Y2Nj/2NjY/9jY2P/Y2Nj/2Rk + ZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2Rk + ZP9kZGT/ZGRk/2VlZf9lZWX/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9lZWX/ZWVl/2RkZP9lZWX/ZWVl/2Vl + Zf9lZWX/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9jY2P/ZGRk/2RkZP9kZGT/ZGRk/2Vl + Zf9lZWX/ZGRk/2VlZf9lZWX/ZmZm/2ZmZv9mZmb/ZWVl/2RkZP9mZmb/T1BP/y8uLv8xMTH/LCwt/ygo + KP8sLCz/Ly8v/ywqK/9NVVP/eH99/4F2e/99Wmn/kk5t/6I5Zv+fHFH/mwI//5cANf+WADj/lwI9/5UA + Ov+VADn/kwA4/5MAN/+SADb/kQA1/48ANP+NADH/jgAy/48AM/+QADT/kQA1/5IANv+TADf/kgA4/5oC + PP9zUmH/MTk2/zk3OP88PDz/ODg4/zo6Ov84ODj/MDAw/yssLP8yMzL/PDw8/z8/Pv88Ozr/Ly4u/yIi + If8xMTD/KCcn/0A+Pf9CQD//TUxK/0E/P/8tLCv/Hx4d/ysrK/8yMjL/LS0u/z4+Pv9lZWT/ZWVl/2Rk + ZP9jY2P/Y2Nj/2RkZP9kZGT/Y2Nj/2RkZP9kZGT/Y2Nj/2RkZP9jY2P/ZGRk/2NjY/9jY2P/Y2Nj/2Rk + ZP9kZGT/ZWVl/2VlZf9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZGRk/2Vl + Zf9lZWX/ZWVl/2RkZP9kZGT/ZWVl/2RkZP9kZGT/ZWVl/2VlZf9lZWX/ZGRk/2VlZf9kZGT/ZWVl/2Vl + Zf9kZGT/ZWVl/2VlZf9lZWX/ZGRk/2VlZf9kZGT/ZGRk/2RkZP9lZWX/ZGRk/2RkZP9kZGT/ZWVl/2Zm + Zv9mZmb/ZWVl/2VlZf9jY2P/X19f/1tbW/9UVFP/TExM/0ZGRv8/Pz7/MDAw/zExMf8zMzP/NTU1/zc2 + Nv8yLjD/PUZD/49Yc/+SGEn/mAhF/58AQ/+eAD3/mAA4/5cAOv+YAD3/mAM//5cBPf+VADr/lQA5/5QA + OP+SADf/kgA2/5EANf+QADT/jwAz/4wAMP+NADH/jgAy/48AM/+QADT/kQA1/5IANv+SAjj/lQA0/5As + VP9FT0z/NDIy/zs7O/83ODj/Hh4e/xYUFP8cGhr/Ly4t/x8eHf8ZGBf/LCws/z09PP83Nzf/OTk4/yYm + Jv80MzL/RkRD/z07Ov9ZWFX/WVhW/zY1NP8fHh3/JiYm/zIyMv8wMDD/MTAw/1ZWVf9nZ2f/ZGNj/2Rk + ZP9jY2P/Y2Nj/2RkZP9jY2P/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Rk + ZP9lZWX/ZGRk/2VlZf9kZGT/ZGRk/2RkZP9lZWX/ZWVl/2VlZf9lZWX/ZmZm/2ZmZv9lZWX/ZWVl/2Vl + Zf9lZWX/ZGRk/2VlZf9lZWX/ZGRk/2RkZP9lZWX/ZWVl/2RkZP9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2Vl + Zf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9kZGT/ZWVl/2ZmZv9mZmb/ZmZm/2VmZv9lZWX/YmJi/15e + Xv9XWFf/UFBQ/0hISP9APz//OTg4/zQ0M/8xMTH/MjIy/zMzM/83Njb/NzU2/zYzNP80MzP/LzIw/yQy + LP9ZSlP/pAlL/54APv+cAEH/mgBA/5kCQf+aA0D/mQI+/5cAPP+WADv/lgA6/5QAOf+UADj/kwA3/5IA + Nv+RADX/kAA0/48AM/+OADL/iwAv/4wAMP+NADH/jgAy/48AM/+QADT/kQA1/5IANv+RATb/mQM7/25R + Xf8yOTb/Ojg5/zk5Of8kJCT/Pz08/0pIR/9OTEv/ODY1/yMhIf8bGhn/KCgn/0FBQP9AQED/ODg4/y4t + Lf89PDv/QT8+/0ZEQv9LSUj/QD49/yclJf8dHBz/MjIy/zExMf8tLS3/QEBA/2VlZf9lZWX/ZGRk/2Nj + Y/9jY2P/Y2Nj/2NjY/9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2RkZP9lZWX/ZWVl/2VlZf9kZGT/ZGRk/2VlZf9mZmb/ZWVl/2VlZf9mZmb/ZWVl/2Vl + Zf9lZWX/ZGRk/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2Zm + Zv9lZWX/ZWVl/2ZmZv9mZmb/Z2dn/2ZmZv9lZWX/ZGRk/2BgYP9bW1v/VFRU/0xMS/9DQ0L/PTw8/zY2 + Nv8zMjL/MjIy/zMzMv80NDT/NzY2/zg1Nv81MjP/MDAw/ywwLv8sNjH/MDs3/zo+Pf9JOED/Z0BT/5MU + S/+eAED/mgJC/5sBQf+aAD//mQA+/5gAPf+XADz/lgA7/5UAO/+UADn/lAA4/5MAN/+SADb/kQA1/5AA + NP+PADP/jgAy/40AMf+KAC7/iwAv/4wAMP+NADH/jgAy/48AM/+QADT/kQA1/5ICN/+UADP/kSpS/0NM + Sf81MzT/Ojo6/z09PP84Nzf/PDo4/1VUUv83NTX/ODY1/zU0M/8lJST/Pj49/zw8PP81NTX/MDAw/zEx + Mf84ODf/Pjw7/zo4N/9APz7/MTAw/yYmJv8xMTH/MTEx/zAwMP8xMTH/WFhY/2dnZ/9jY2P/ZGRk/2Rk + ZP9jY2P/Y2Nj/2NjY/9jY2P/ZGRk/2NjY/9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Rk + ZP9kZGT/ZGRk/2VlZf9lZWX/ZWVl/2RkZP9kZGT/ZmZm/2VlZf9lZWX/ZWVl/2VlZf9mZmb/ZWVl/2Vl + Zf9kZGT/ZWVl/2VlZf9mZmb/ZmZm/2ZmZv9mZmb/ZmZm/2VmZf9lZWX/ZmZm/2ZmZv9mZmb/Z2dn/2Zm + Zv9mZmb/ZmZm/2NkY/9fX1//WFlY/1FRUP9HSEf/Pz8//zk5Of80NDP/MjIy/zMzM/80NDT/NTQ0/zY0 + Nf82MzT/NjQ0/zM0M/8vNTL/KzUx/y46Nf87Pz7/UD9I/2g3Tv9/KE7/kxhN/6AJSv+lAEb/ngBB/5sB + Qv+aAED/mgA//5kAPv+YAD3/lwA8/5YAO/+WADr/lQA5/5QAOP+TADf/kgA2/5EANf+QADT/jwAz/44A + Mv+NADH/jAAw/4oALf+LAC7/iwAv/4wAMP+NADH/jgAy/48AM/+QADT/kQA1/5EBNv+YATj/akJS/zI7 + OP84NTb/Pj4+/zo6Ov82NDP/UE9M/0JAP/81MzL/Li0s/y0tLf8+Pj7/IiMj/y0sK/8pKCf/ICAf/y8v + L/8zMzP/MDAw/zIyMv8zMzP/MDAw/zAwMP8xMTH/MTEx/y0tLf9DQ0P/Z2dm/2VlZf9kZGT/Y2Nj/2Nj + Y/9jY2P/Y2Nj/2RkZP9jY2P/Y2Nj/2NjY/9jY2P/ZGRk/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Vl + Zf9lZWX/ZWVl/2VlZf9mZmb/ZWVl/2ZmZv9lZWX/ZmZm/2ZmZv9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2Rk + ZP9lZWX/ZmZm/2ZmZv9mZmb/ZmZm/2VlZf9mZmb/Z2dn/2dnZ/9naGj/Z2dn/2ZmZv9hYWH/XFxc/1VV + VP9MTEv/RERD/zw8PP82Njb/MzMz/zIyMv80NDT/NTU1/zc2Nv83NDX/NDIz/zAvL/8rMC3/KjMv/y05 + NP82Pzv/RUJF/1g9Sv9xOFL/iCtU/5seVf+kC03/pgBH/6QARP+gAEL/nABB/5oAQf+aAUH/mwBA/5kA + P/+ZAD7/mAA9/5cAPP+WADv/lQA6/5QAOf+UADj/kwA3/5IANv+RADX/kAA0/48AM/+OADL/jQAx/4wA + MP+LAC//iQAs/4oALf+KAC7/iwAv/4wAMP+NADH/jgAy/48AM/+QADT/kQE2/5IAM/+UHEn/TE5N/zMz + M/86OTn/QkJB/zU0NP8yMC//NDMy/zc2Nf8sKyv/Ozs7/ykqKv8sKyv/Q0A//05MS/83NjX/GhkY/y4u + Lv8yMzP/MDAw/zAwMP8uLi7/MTEx/zExMf8xMTH/MDAw/zIyMv9aWln/aGho/2RkZP9kZGT/Y2Nj/2Nj + Y/9jY2P/Y2Nj/2NjY/9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2NjY/9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2Vl + Zf9lZWX/ZWVl/2VlZf9lZWX/ZWVl/2VlZf9mZmb/ZmZm/2ZmZv9lZWX/ZmVl/2ZmZv9mZmb/ZmZm/2Zm + Zv9nZ2f/ZmZm/2dmZ/9oaGj/aGho/2dnZ/9kZGT/X19f/1hYWP9QUE//R0ZG/z4+Pv84ODj/NDQ0/zMz + M/8zMzP/NTU1/zY1Nv85Nzf/ODU2/zQyM/8vMS//KjEt/yo2MP8wOzb/PUA//1A/SP9nO1D/gDRY/5Ih + Vf+hFVT/pwZO/6kASv+lAEX/oQBD/54AQ/+cAEP/nAFD/5wBQ/+cAEL/mwBB/5oAQP+aAD//mAA+/5gA + Pf+XADz/lgA7/5UAOv+UADn/kwA4/5MAN/+SADb/kQA1/5AANP+PADP/jgAy/40AMf+MADD/iwAv/4oA + Lv+IACv/iQAs/4oALf+KAC7/iwAv/4wAMP+NADH/jgAy/48AM/+QADT/kAE2/5YANP9/MlD/N0E9/zc0 + Nf87PDv/PDs7/zs7Ov89Pj3/PT09/z4+Pv88PT3/Jygn/zk3Nv83NTT/NDIy/0FAP/8tLCz/ISAf/zMz + M/8zMzP/MTIx/y8vL/8yMjL/MTEx/zExMf8xMTH/Li4u/0ZGRv9nZ2f/ZGRl/2RkZP9jY2P/ZGRk/2Nj + Y/9jY2P/ZGRk/2NjY/9jY2P/ZGRk/2RkZP9kZGT/Y2Nj/2VlZf9lZWX/ZWVl/2VlZf9kZGT/ZGRk/2Rk + ZP9mZmb/ZmZm/2VlZf9lZWX/ZmZm/2VlZf9mZmb/ZmZm/2ZmZv9mZmb/ZmZm/2ZmZv9nZ2f/Z2dn/2dn + Z/9lZWX/YmJh/1xcW/9UVFT/TExL/0NDQv86Ojr/NTU1/zMzM/8zMzP/NDQ0/zY2Nv83NTb/NjQ1/zUy + M/8xMjH/LzMx/yw2Mf8tOjT/NT46/0U/Qv9bPUz/czVS/4wpV/+dGVX/pwpS/6oATf+pAEn/pQBH/6EA + Rf+fAEX/ngBF/54BRf+eAUX/nQBE/50AQ/+cAEL/mwBB/5sAQP+aAED/mQA+/5gAPv+XAD3/lwA8/5YA + O/+VADr/lAA5/5MAOP+TADf/kQA2/5EANf+QADT/jwAz/44AMv+NADH/jAAw/4sAL/+KAC7/iQAt/4cA + Kv+IACv/iQAs/4kALf+LAC7/iwAv/4wAMP+NADH/jgAy/48AM/+QADT/jwE1/5cCN/9mQVD/MTs3/zk3 + OP86Ojr/ODg4/zk5OP89PT3/Pj4+/z09Pf80NDP/NjU0/z89PP9bWlj/U1JQ/zg3Nv8gHx//MDAv/z4+ + Pv8vLy//MDAw/zExMf8xMTH/MTEx/zAwMP8vLy//NTQ0/11dXP9nZ2f/ZGRk/2RkZP9kZGT/Y2Nj/2Nj + Y/9jY2P/Y2Nj/2NjY/9jY2P/Y2Nj/2NjY/9kZGT/ZWVl/2RkZP9kZGT/ZGRk/2VlZf9kZGT/ZWVl/2Zm + Zv9mZmb/ZmZm/2VlZf9mZmb/ZmZm/2dnZ/9oaGj/aGho/2dnZ/9mZmb/ZGRk/19fX/9ZWVn/UFBP/0dH + Rv8/Pz7/ODg4/zQ0NP8zMzP/NDQ0/zY1Nv84Nzf/ODY3/zY0Nf8zMjL/LjEw/yw0MP8tOTP/ND86/0BB + Qf9TQUv/bD9W/4EuVv+XI1n/pBFU/6sGUv+sAEz/qQBJ/6UASP+iAEj/oABI/6ABSP+gAUf/oAFH/58A + Rv+fAEX/ngBE/50AQ/+cAEL/nABB/5sAQf+aAED/mgA//5kAPv+YAD3/lwA9/5YAPP+WADv/lQA6/5QA + Of+TADj/kgA3/5IANv+RADX/kAA0/48AM/+OADL/jQAx/4wAMP+LAC//igAu/4oALf+JACz/hgAp/4cA + Kv+IACv/iQAs/4oALf+KAC7/jAAv/4wAMP+NADH/jgAy/48AM/+PATX/kQAz/5QPQP9QREn/MjY0/zo5 + Of87Ozv/ODg3/zo6Of8+Pj7/Pj4+/zg4OP80NDP/Ojg3/0ZEQv9APj3/Ojg3/ykoKP8jIyL/NTY1/zU1 + Nf8wMDD/MTEx/zExMf8xMTH/MTEx/zExMf8uLi7/SkpJ/2dnZ/9kZGT/ZGRk/2NjY/9jY2P/YmJi/2Nj + Y/9jY2P/Y2Nj/2NjY/9jY2P/Y2Nj/2RkZP9kZGT/ZGRk/2RkZP9kZGT/ZGRk/2VlZf9mZmb/ZmZm/2dn + Z/9mZmb/aGho/2hoaP9nZ2f/ZmZm/2NjY/9cXFz/VVVV/0xMS/9DQ0P/Ozs7/zc3Nv80NDP/NDQ0/zU1 + Nf83Nzf/Ojg5/zk3OP82NDX/MTIx/y0yL/8rNTD/Ljo1/zo/Pf9MQkj/YjxP/3szVf+SKlz/oRZY/6oJ + VP+tAVD/rABM/6gASf+kAEn/ogBJ/6EBSf+hAUn/oQFJ/6EASP+hAEf/oABG/58ARv+fAEX/ngBE/50A + Q/+dAEP/nABC/5sAQf+bAED/mgBA/5kAP/+YAD7/mAA9/5cAPP+WADv/lQA7/5UAOv+UADn/kwA4/5IA + N/+RADb/kAA1/5AANP+PADP/jgAy/40AMf+MADD/iwAv/4oALv+KAC3/iQAs/4gAK/+FACj/hgAp/4cA + Kv+IACv/iQAs/4oALf+KAC7/iwAv/4wAMP+NADH/jgAy/48AM/+PATT/kgAy/4sZRP9FSUj/NTY1/zo5 + Ov88PDz/PDw7/z8+Pv9CQkH/QkJC/zw8PP86OTn/Ojk5/z09PP88Ozv/Ly8u/zIyMv9AQED/Ojo6/zAw + MP8wMDD/MTEx/zExMf8xMTH/MTEw/y8vL/83Nzf/YGBg/2ZmZv9jY2P/Y2Nj/2NjY/9jY2P/Y2Nj/2Nj + Y/9jY2P/ZGRk/2NjY/9kZGT/ZGRk/2RkZP9kZGT/ZWVl/2ZmZv9lZWX/ZmZm/2ZmZv9nZ2f/Zmdn/2Rk + ZP9gYGD/WVlY/1BQT/9GR0b/Pz8//zg4OP81NDT/MzMz/zQ0NP82Njb/ODc4/zk2N/83NTX/MzIy/y8y + MP8tNjH/LTo0/zQ+Ov9APD//VD1J/3E9Vv+IK1f/mhlW/6gOVv+tA1L/rQBO/6oAS/+mAEr/pABK/6IA + Sv+iAUv/ogFL/6IBSv+iAEn/ogBI/6EASP+hAEf/oABG/58ARv+fAEX/ngBE/54ARP+dAEP/nABC/5wA + Qf+bAEH/mgBA/5oAP/+ZAD7/mAA+/5cAPf+XADz/lgA7/5UAOv+UADn/lAA4/5MAN/+SADb/kQA2/5AA + Nf+QADT/jwAz/44AMv+NADH/jAAw/4sAL/+KAC7/iQAt/4gALP+IACv/hwAq/4QAJ/+FACj/hgAp/4cA + Kv+IACv/iQAs/4kALf+KAC7/iwAv/4wAMP+NADH/jgAy/48AM/+OATT/lQAz/4MnSv86QT//NjY2/zs6 + Ov87Ozv/Ozs7/z09PP9AQED/QEBA/0BAQP9BQUH/Pj8+/zs7O/89PT3/QEBA/z4+Pv8/Pz//PDw7/zU0 + NP8wMDD/Ly8v/zExMf8xMTH/MTEx/y4uLv9PUE7/Z2dn/2NjY/9jY2P/Y2Nj/2JjY/9jY2P/Y2Nj/2Nj + Y/9kZGT/ZGRk/2RkZP9kZGT/ZWVl/2VlZf9mZmb/Z2dn/2VlZf9jY2P/Xl5e/1VVVf9MTEz/Q0NC/zs7 + Ov82NjX/MzMz/zQ0NP81NTX/NzY3/zk3OP83NTb/NjQ0/y8xMP8rMS7/LDcy/zI9OP88QkD/TD5F/2Q8 + UP98LlT/kyNY/6IQVf+sB1T/rwBR/6wATf+oAEv/pQBL/6MAS/+jAUv/owFM/6MBS/+jAEr/owBK/6IA + Sf+iAEn/ogBI/6EASP+gAEf/oABG/58ARv+fAEX/ngBE/54ARP+dAEP/nQBC/5wAQv+bAEH/mgBA/5oA + QP+ZAD//mAA+/5gAPf+XADz/lgA7/5YAO/+VADr/lAA5/5MAOP+SADf/kgA2/5EANf+QADX/jwAz/48A + M/+OADL/jQAx/4wAMP+LAC//igAu/4kALf+JACz/iAAr/4cAKv+GACn/gwAm/4QAJ/+FACj/hgAp/4cA + Kv+IACv/iQAs/4kALf+KAC7/iwAv/4wAMP+NADH/jgAx/48AM/+OATP/lQAy/3kdP/84Pz3/NjY2/zs6 + Ov87Ozv/PDw8/zw8PP88PDz/PT09/zw8PP88PDz/PT09/z09Pf89PT3/Pj4+/z4+Pv8+Pj7/Pz8+/zo6 + Ov81NTT/MDAw/y8vL/8xMTH/Li4v/zs7Ov9mZmX/Y2Nj/2JiYv9iYmL/YmJi/2JiYv9jY2P/Y2Nj/2Rk + ZP9lZWX/Z2dn/2dnZ/9mZmb/YmJi/1xcXP9TU1P/SUlI/0BAP/85ODj/NDQ0/zMzM/80NDT/NjY2/zk4 + OP85Nzj/NjQ1/zQ0NP8uMjD/LDUw/y46Nf83QT3/RUJE/1tDT/90OlX/iy5a/50cWP+pDFX/rgFR/64A + Tv+qAEv/pwBL/6QAS/+jAEv/owFM/6QBTP+kAUv/pABL/6MASv+jAEr/owBJ/6IASf+iAEj/oQBI/6EA + R/+gAEf/oABG/58ARv+fAEX/ngBF/54ARP+dAEP/nQBC/5wAQv+bAEH/mwBA/5oAQP+ZAD//mQA+/5gA + Pf+XAD3/lwA8/5YAO/+VADr/lQA5/5QAOf+TADj/kgA3/5EANv+RADX/kAA0/48AM/+OADL/jgAx/40A + MP+MADD/iwAv/4oALv+JAC3/iAAs/4gAK/+HACr/hgAp/4UAKP+CACX/gwAm/4QAJ/+FACj/hgAp/4cA + Kv+IACv/iQAs/4kALf+KAC7/iwAv/4wAMP+NADD/jQAx/44AMv+OATP/lgAy/3gcPv87QkD/NTY1/zs5 + Ov87Ozv/PDw8/z09Pf8+Pj7/PT09/z09Pf88PDz/PDw8/z4+Pv89PT3/PDw8/z09Pf89PT3/Pj4+/z4+ + Pv87Ozv/MzMz/y8vL/8xMjL/Li4u/1hYVv9sbGz/YmJi/2VlZf9nZ2f/aGho/2pqav9qamr/Z2dn/2Ji + Yf9aWln/UFBP/0ZGRf89PTz/Nzc3/zQ0M/80NDT/NTU2/zg3N/86ODn/OTY3/zY0NP8yNDP/LjUx/yw3 + Mv8wOzb/PT8//1BBSf9pQVb/fzFX/5YnWv+kFFf/rQlV/60AT/+rAEz/qABL/6UASv+jAEv/owFM/6QB + TP+kAUv/pABL/6QAS/+jAEr/owBK/6MASv+iAEn/ogBJ/6IASP+hAEj/oQBH/6AAR/+gAEf/oABG/58A + Rf+fAEX/ngBE/54ARP+dAEP/nQBC/5wAQv+bAEH/mwBB/5oAQP+aAD//mQA+/5gAPv+YAD3/lwA8/5YA + O/+WADv/lQA6/5QAOf+TADj/kwA3/5IAN/+RADb/kQA1/5AANP+PADP/jgAy/40AMf+NADD/jAAv/4sA + Lv+KAC7/iQAt/4kAK/+HACv/hwAq/4YAKf+FACj/hAAn/4EAJP+CACX/gwAm/4QAJ/+FACj/hgAp/4cA + Kv+IACv/iAAr/4kALP+KAC3/iwAu/4wAL/+NADD/jQAx/44AMv+NAjP/lAAx/4ktT/9ESEj/MjY1/zs4 + Of87Ozv/OTk5/zIyMv80NDT/NDQ0/zo6Ov88PDz/PT09/z09Pf88PDz/PT09/z09Pf89PT3/PT09/z8/ + P/8+Pj7/ODg4/zExMf8tLi7/Pz4+/3FxcP9zdHL/cXJw/2prav9jY2L/WFhX/0xMS/9BQUD/OTk5/zQ0 + NP8zMzP/MzMz/zY1Nv84Nzf/OTc4/zc1Nf8yMjH/LzMw/y42Mv8uOjT/ND46/0Q/Qv9aPUv/dDdT/4sp + Vv+cGVb/pwpT/60BUP+sAEz/qABK/6UASf+jAEr/owBL/6MBS/+jAUv/pAFL/6QAS/+kAEr/owBK/6MA + Sv+jAEr/owBJ/6IASf+iAEn/oQBI/6EASP+hAEf/oQBH/6AAR/+gAEb/nwBF/58ARf+eAET/ngBE/54A + Q/+dAEP/nABC/5wAQv+bAEH/mwBB/5oAQP+aAD//mQA+/5gAPv+YAD3/lwA8/5cAPP+WADv/lQA6/5UA + Of+UADn/kwA4/5IAN/+SADb/kQA1/5AANP+PADT/jwAz/44AMv+NADH/jAAw/4sAL/+LAC7/igAt/4kA + LP+IACz/hwAq/4YAKv+GACn/hQAo/4QAJ/+DACb/gAAj/4EAJP+CACX/gwAm/4QAJv+FACj/hgAo/4YA + Kf+HACr/iAAr/4kALP+KAC3/iwAu/4sAL/+MADD/jQAx/44AMv+NATL/lAAy/4obQv9PQ0j/MTo3/zUy + M/9DQkL/c3Nz/42Pjv99f3//REVF/zk5Of88PDz/Ozs7/zw8PP87Ozv/PDw8/zw8PP88PDz/PDw8/z09 + Pf8/QD//Ozs7/zExMf8wMC//UlJR/1dXVv9HR0b/PDw7/zY1Nf8yMjL/MzMz/zU1Nf83Njb/ODc3/zc1 + Nv80MjL/MDEw/ywzMP8tODP/Mj04/z5DQv9QQkn/aEBT/30wVP+TJlj/ohNU/6kFT/+rAEz/qQBJ/6YA + Sf+jAEn/oQBJ/6IBSv+iAUr/owFK/6MASv+jAEr/owBK/6MASf+jAEn/ogBJ/6IASf+iAEn/ogBI/6IA + SP+hAEj/oQBH/6EAR/+gAEf/oABG/6AARv+fAEb/nwBF/54ARf+eAET/ngBE/50AQ/+dAEP/nABC/5wA + Qv+bAEH/mgBA/5oAQP+aAD//mQA//5gAPv+YAD3/lwA9/5cAPP+WADv/lQA6/5UAOv+UADn/lAA4/5MA + N/+SADf/kQA2/5AANf+QADT/jwAz/44AMv+OADL/jQAx/4wAMP+LAC//iwAu/4oALf+JACz/iAAr/4cA + Kv+GACn/hgAp/4UAJ/+EACb/gwAl/4IAJP+AACL/gAAj/4EAI/+CACT/gwAl/4QAJv+FACf/hQAo/4YA + Kf+HACr/iAAr/4kALP+KAC3/igAu/4sAL/+MADD/jQAw/44AMf+NATL/kgAx/5EOOv9pQlH/PEpG/z4+ + Pf9oZmX/qKim/66vr/89PT7/Ojg5/zw7O/88PDz/Ozs7/zw8PP88Ozv/PDw8/zw8PP87Ojv/Ozs7/zs7 + O/89PT3/Ojo6/zQ0NP83Nzb/NjY2/zU0Nf82NTb/ODY3/zk3OP83NTX/MzMy/y4zMP8sNTH/Ljo0/zhA + Pf9HQ0X/Wz5L/3U9Vv+LL1j/mx5V/6YOUv+pAUz/qQBJ/6YARv+iAEb/oQBI/6AASP+hAUn/ogFJ/6IA + Sf+iAEn/ogBJ/6IASf+iAEn/ogBI/6IASP+iAEj/oQBI/6EASP+hAEj/oQBH/6EAR/+hAEf/oABG/6AA + Rv+gAEb/nwBG/58ARf+fAEX/ngBF/54ARP+eAET/nQBD/50AQ/+cAEL/nABC/5sAQf+bAEH/mwBA/5oA + QP+ZAD//mQA//5gAPv+YAD3/lwA9/5cAPP+WADv/lgA6/5UAOv+UADn/lAA4/5MAOP+SADf/kgA2/5EA + Nf+QADX/kAA0/48AM/+OADL/jQAx/40AMP+MAC//iwAv/4oALv+KAC3/iQAs/4gAK/+HACr/hgAp/4UA + KP+EACf/hAAm/4MAJf+CACT/gQAj/38AIf9/ACH/gAAi/4EAI/+CACT/gwAl/4QAJv+FACf/hQAo/4YA + Kf+HACr/iAAr/4kALP+JAC3/igAu/4sALv+MAC//jAAw/40AMf+NATP/jgAv/5gJOf+LRF7/TlBR/yMr + Kf9NS0r/Z2lo/zEzM/8zODb/MjUz/zAtLf8yMDH/MC4v/zAuL/8tKiv/LCor/zQ1NP86Nzj/Ojk5/zo6 + Ov87Ojr/Ojg5/zg2N/82NDX/NTQ0/zEzMv8tNTH/Ljk0/zM9Of8/Pz//Uj9I/2g8T/+BNlb/kiJT/6AV + Uf+lBUr/pwBI/6UARf+hAET/nwBE/54ARv+fAUf/oAFH/6ABR/+hAEf/oQBH/6EAR/+hAEf/oQBH/6EA + R/+hAEf/oQBH/6EAR/+hAEf/oABH/6AAR/+gAEf/oABG/6AARv+gAEb/nwBG/58ARf+fAEX/nwBF/54A + Rf+eAET/ngBE/50ARP+dAEP/nQBD/5wAQv+cAEL/nABB/5sAQf+bAEH/mgBA/5oAP/+ZAD//mQA+/5gA + Pv+YAD3/lwA8/5cAPP+WADv/lgA7/5UAOv+UADn/lAA4/5MAOP+SADf/kgA3/5EANv+QADX/kAA0/48A + M/+PADL/jgAy/40AMf+MADD/iwAv/4sALv+KAC7/iQAt/4kALP+HACv/hwAq/4YAKf+FACj/hAAn/4QA + Jv+DACX/ggAk/4EAI/+AACL/fwAh/38AIf9/ACH/gAAi/4EAI/+CACT/gwAl/4QAJv+EACf/hQAo/4YA + Kf+HACr/iAAr/4gAK/+JACz/igAt/4oALv+LAC//jAAw/40AMP+NATL/jAAw/5EALv+TIEn/aEVS/0JG + Rf85MzX/R0BD/1I8RP9ZTVL/ZHJv/2ZvbP+RmJb/pK6r/56rqP99hoX/SUhJ/zM9Of8yODb/MjQy/zE0 + Mv8uNjP/Ljk0/zI9OP88QkD/TUVJ/145Sf90L03/iiZR/5gTS/+hCEn/pQBG/6QAQ/+hAEL/ngBB/50A + Q/+dAET/ngFF/54BRf+fAUX/nwBG/58ARv+fAEb/nwBG/58ARv+gAEb/nwBG/6AARv+gAEb/nwBG/58A + Rv+gAEb/nwBG/58ARf+fAEX/nwBF/58ARf+fAEX/nwBF/54ARf+eAET/ngBE/54ARP+eAEP/nQBD/50A + Q/+cAEL/nABC/5wAQv+bAEH/mwBB/5sAQP+aAED/mgA//5kAP/+ZAD7/mQA+/5gAPf+XAD3/lwA8/5cA + PP+WADv/lgA6/5UAOv+UADn/lAA5/5MAOP+TADf/kgA2/5EANv+RADX/kAA0/48ANP+PADP/jgAy/40A + Mf+NADD/jAAw/4sAL/+LAC7/igAt/4kALP+IACv/iAAq/4cAKv+GACn/hQAo/4QAJ/+DACb/gwAl/4IA + JP+BACP/gAAi/38AIf9/ACH/fwAh/38AIf9/ACH/gAAi/4EAI/+CACT/gwAl/4MAJv+EACf/hQAo/4UA + Kf+GACr/hwAq/4gAK/+JACz/iQAt/4oALv+LAC//jAAv/4wAMP+NADH/jQEz/44ALv+TATT/liJM/5ER + QP+QCzv/lwg9/5wXSP+sX3z/rISV/7mgrP/Emav/yIig/7dReP+YGUr/dylI/1c9SP9QSk7/VEVM/2RC + Uf91OFL/hCdO/5McTv+eEUz/oQFD/6IAQf+fAD//nAA//5sAQP+aAEH/mwFC/5wBQ/+dAUP/nQBD/50A + Q/+dAEP/nQBE/54ARP+eAET/ngBE/54ARP+eAET/ngBE/54ARP+eAET/ngBE/54ARP+eAET/ngBF/54A + RP+eAET/ngBE/54ARP+eAET/nQBE/50ARP+dAEP/nQBD/50AQ/+dAEP/nABC/5wAQv+cAEL/nABB/5sA + Qf+bAEH/mwBA/5oAQP+aAED/mQA//5kAP/+ZAD7/mAA+/5gAPf+XAD3/lwA8/5cAPP+WADv/lQA7/5UA + Ov+UADn/lAA5/5MAOP+TADf/kgA3/5EANv+RADX/kAA0/5AANP+PADP/jgAy/40AMv+NADH/jAAw/4wA + L/+LAC7/igAu/4oALf+JACz/iAAr/4cAKv+GACn/hgAo/4UAJ/+EACf/gwAm/4IAJf+CACT/gQAj/4AA + Iv9/ACH/fwAh/38AIf9/ACH/fwAh/38AIf9/ACH/gAAi/4EAI/+CACT/ggAl/4MAJf+EACb/hQAn/4UA + KP+GACn/hwAq/4gAK/+IACv/iQAs/4oALf+KAC7/iwAv/4wAMP+NADD/jQEy/40AMf+OAC7/kAAx/5AA + M/+PADP/jwAx/40AK/+SADL/kgA0/48AL/+MACr/jgAt/5UANv+bADn/nAVB/5oQR/+bCkT/ngJA/54A + Pf+cADv/mgA7/5gAO/+YAD7/mAE//5kBQP+aAUD/mgBA/5sAQP+bAEH/mwBB/5sAQf+bAEH/nABC/5wA + Qv+cAEL/nABC/50AQv+dAEL/nQBD/50AQ/+dAEP/nQBD/50AQ/+dAEP/nQBD/50AQ/+dAEP/nQBD/50A + Q/+dAEP/nABC/5wAQv+cAEL/nABC/5wAQv+cAEL/nABB/5sAQf+bAEH/mwBB/5sAQP+aAED/mgBA/5oA + P/+ZAD//mQA//5kAPv+YAD7/mAA9/5cAPf+XADz/lgA8/5YAO/+WADv/lQA6/5QAOv+UADn/lAA4/5MA + OP+TADf/kgA3/5EANv+RADX/kAA1/5AANP+PADP/jgAy/44AMv+NADH/jAAw/4wAL/+LAC//iwAu/4oA + Lf+JACz/iAAs/4gAK/+HACr/hgAp/4UAKP+EACf/hAAn/4MAJv+CACX/gQAk/4EAI/+AACL/fwAh/38A + If9/ACH/fwAh/38AIf9/ACH/fwAh/38AIf9/ACH/gAAi/4AAI/+BACT/ggAl/4MAJf+EACb/hAAn/4UA + KP+GACn/hwAq/4cAKv+IACv/iQAs/4oALf+KAC3/iwAu/4wAL/+MADD/jQAx/40BMv+OATP/jgEz/48A + NP+QATX/kQM3/5EBNv+RADb/kgI4/5QEOv+UAzr/kwE5/5MBOf+TADj/lAA3/5QAOP+UADr/lQE7/5YB + PP+XAT3/lwE9/5gAPf+YAD7/mAA+/5kAPv+ZAD//mQA//5oAP/+aAED/mgBA/5oAQP+bAED/mwBA/5sA + Qf+bAEH/mwBB/5sAQf+bAEH/mwBB/5wAQf+cAEH/nABB/5wAQf+cAEH/nABB/5wAQf+bAEH/mwBB/5sA + Qf+bAEH/mwBB/5sAQf+bAEH/mwBA/5oAQP+aAED/mgBA/5oAP/+aAD//mQA//5kAP/+ZAD7/mAA+/5gA + Pf+YAD3/mAA9/5cAPP+XADz/lgA7/5YAO/+VADr/lQA6/5UAOf+UADn/lAA4/5MAOP+SADf/kgA2/5IA + Nv+RADX/kQA1/5AANP+PADP/jwAz/44AMv+NADH/jQAw/4wAMP+LAC//iwAu/4oALv+JAC3/iQAs/4gA + K/+HACr/hwAq/4YAKP+FACj/hAAn/4QAJv+DACX/ggAk/4EAJP+AACP/gAAi/38AIf9/ACH/fwAh/38A + If8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAA= + + + \ No newline at end of file diff --git a/CHOVY-TRANSFER/PSVIMGBuilder.cs b/CHOVY-TRANSFER/PSVIMGBuilder.cs new file mode 100644 index 0000000..c17ea36 --- /dev/null +++ b/CHOVY-TRANSFER/PSVIMGBuilder.cs @@ -0,0 +1,488 @@ +using Org.BouncyCastle.Crypto.Digests; +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using System.Threading; +using static PSVIMGTOOLS.SceIoStat; + +namespace PSVIMGTOOLS +{ + class PSVIMGBuilder + { + private byte[] IV = new byte[0x10]; + private byte[] KEY; + private Random rnd = new Random(); + private Stream mainStream; + private Sha256Digest shaCtx; + private byte[] blockData; + private MemoryStream blockStream; + private long contentSize = 0; + + + //async + private int blocksWritten = 0; + private bool finished = false; + + public Int64 ContentSize + { + get + { + return contentSize; + } + } + public Int32 BlocksWritten + { + get + { + return blocksWritten; + } + } + + public Boolean HasFinished + { + get + { + return finished; + } + } + + //Footer + private long totalBytes = 0; + + private byte[] aes_cbc_encrypt(byte[] plainText, byte[] IV, byte[] KEY, int size=-1) + { + if (size < 0) + { + size = plainText.Length; + } + + MemoryStream ms = new MemoryStream(); + /* + *- DEBUG Disable Encryption + ms.Write(plainText, 0x00, size); + ms.Seek(0x00,SeekOrigin.Begin); + return ms.ToArray();*/ + + Aes alg = Aes.Create(); + alg.Mode = CipherMode.CBC; + alg.Padding = PaddingMode.None; + alg.KeySize = 256; + alg.BlockSize = 128; + alg.Key = KEY; + alg.IV = IV; + CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write); + cs.Write(plainText, 0, size); + cs.Close(); + byte[] cipherText = ms.ToArray(); + return cipherText; + } + + private byte[] aes_ecb_encrypt(byte[] plainText, byte[] KEY, int size = -1) + { + if (size < 0) + { + size = plainText.Length; + } + + MemoryStream ms = new MemoryStream(); + /* + *- DEBUG Disable Encryption + ms.Write(plainText, 0x00, size); + ms.Seek(0x00,SeekOrigin.Begin); + return ms.ToArray();*/ + + Aes alg = Aes.Create(); + alg.Mode = CipherMode.ECB; + alg.Padding = PaddingMode.None; + alg.KeySize = 256; + alg.BlockSize = 128; + alg.Key = KEY; + CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write); + cs.Write(plainText, 0, size); + cs.Close(); + byte[] cipherText = ms.ToArray(); + return cipherText; + } + + private void writeUInt64(Stream dst,UInt64 value) + { + byte[] ValueBytes = BitConverter.GetBytes(value); + dst.Write(ValueBytes, 0x00, 0x8); + } + private void writeInt64(Stream dst,Int64 value) + { + byte[] ValueBytes = BitConverter.GetBytes(value); + dst.Write(ValueBytes, 0x00, 0x8); + } + private void writeUInt16(Stream dst, UInt16 value) + { + byte[] ValueBytes = BitConverter.GetBytes(value); + dst.Write(ValueBytes, 0x00, 0x2); + } + private void writeInt16(Stream dst, Int16 value) + { + byte[] ValueBytes = BitConverter.GetBytes(value); + dst.Write(ValueBytes, 0x00, 0x2); + } + + private void writeInt32(Stream dst, Int32 value) + { + byte[] ValueBytes = BitConverter.GetBytes(value); + dst.Write(ValueBytes, 0x00, 0x4); + } + private void writeUInt32(Stream dst, UInt32 value) + { + byte[] ValueBytes = BitConverter.GetBytes(value); + dst.Write(ValueBytes, 0x00, 0x4); + } + + private SceDateTime dateTimeToSceDateTime(DateTime dt) + { + SceDateTime sdt = new SceDateTime(); + sdt.Day = Convert.ToUInt16(dt.Day); + sdt.Month = Convert.ToUInt16(dt.Month); + sdt.Year = Convert.ToUInt16(dt.Year); + + + sdt.Hour = Convert.ToUInt16(dt.Hour); + sdt.Minute = Convert.ToUInt16(dt.Minute); + sdt.Second = Convert.ToUInt16(dt.Second); + sdt.Microsecond = Convert.ToUInt32(dt.Millisecond * 1000); + return sdt; + } + + private SceIoStat sceIoStat(string path) + { + SceIoStat stats = new SceIoStat(); + FileAttributes attrbutes = File.GetAttributes(path); + + if (attrbutes.HasFlag(FileAttributes.Directory)) + { + stats.Mode |= Modes.Directory; + stats.Size = 0; + } + else + { + stats.Mode |= Modes.File; + stats.Size = Convert.ToUInt64(new FileInfo(path).Length); + + } + + if(attrbutes.HasFlag(FileAttributes.ReadOnly)) + { + stats.Mode |= Modes.GroupRead; + + stats.Mode |= Modes.OthersRead; + + stats.Mode |= Modes.UserRead; + } + else + { + stats.Mode |= Modes.GroupRead; + stats.Mode |= Modes.GroupWrite; + + stats.Mode |= Modes.OthersRead; + stats.Mode |= Modes.OthersWrite; + + stats.Mode |= Modes.UserRead; + stats.Mode |= Modes.UserWrite; + } + + stats.CreationTime = dateTimeToSceDateTime(File.GetCreationTimeUtc(path)); + stats.AccessTime = dateTimeToSceDateTime(File.GetLastAccessTimeUtc(path)); + stats.ModificaionTime = dateTimeToSceDateTime(File.GetLastWriteTimeUtc(path)); + + return stats; + } + + private void writeSceDateTime(Stream dst,SceDateTime time) + { + writeUInt16(dst, time.Year); + writeUInt16(dst, time.Month); + writeUInt16(dst, time.Day); + + writeUInt16(dst, time.Hour); + writeUInt16(dst, time.Minute); + writeUInt16(dst, time.Second); + writeUInt32(dst, time.Microsecond); + } + + private void writeSceIoStat(Stream dst, SceIoStat stats) + { + writeUInt32(dst, Convert.ToUInt32(stats.Mode)); + writeUInt32(dst, Convert.ToUInt32(stats.Attributes)); + writeUInt64(dst, stats.Size); + writeSceDateTime(dst, stats.CreationTime); + writeSceDateTime(dst, stats.AccessTime); + writeSceDateTime(dst, stats.ModificaionTime); + foreach(UInt32 i in stats.Private) + { + writeUInt32(dst,i); + } + } + + private void memset(byte[] buf, byte content, long length) + { + for(int i = 0; i < length; i++) + { + buf[i] = content; + } + } + + private void writeStringWithPadding(Stream dst, string str, int padSize, byte padByte = 0x78) + { + int StrLen = str.Length; + if(StrLen > padSize) + { + StrLen = padSize; + } + + int PaddingLen = (padSize - StrLen)-1; + writeString(dst, str, StrLen); + dst.WriteByte(0x00); + writePadding(dst, padByte, PaddingLen); + } + + private void writeString(Stream dst, string str, int len=-1) + { + if(len < 0) + { + len = str.Length; + } + + byte[] StrBytes = Encoding.UTF8.GetBytes(str); + dst.Write(StrBytes, 0x00, len); + } + + private void writePadding(Stream dst, byte paddingByte, long paddingLen) + { + byte[] paddingData = new byte[paddingLen]; + memset(paddingData, paddingByte, paddingLen); + dst.Write(paddingData, 0x00, paddingData.Length); + } + private byte[] getHeader(string FilePath, string ParentPath, string PathRel) + { + using (MemoryStream Header = new MemoryStream()) + { + writeInt64(Header, DateTime.UtcNow.Ticks); // SysTime + writeInt64(Header, 0); // Flags + writeSceIoStat(Header, sceIoStat(FilePath)); + writeStringWithPadding(Header, ParentPath, 256); // Parent Path + writeUInt32(Header, 1); //unk_16C + writeStringWithPadding(Header, PathRel, 256); //Relative Path + writePadding(Header, 0x78, 904); //'x' + writeString(Header, PSVIMGConstants.PSVIMG_HEADER_END); //EndOfHeader + Header.Seek(0x00, SeekOrigin.Begin); + return Header.ToArray(); + } + } + + private void startNewBlock() + { + blockData = new byte[PSVIMGConstants.FULL_PSVIMG_SIZE]; + blockStream = new MemoryStream(blockData, 0x00, PSVIMGConstants.FULL_PSVIMG_SIZE); + } + + + private byte[] shaBlock(int length = PSVIMGConstants.PSVIMG_BLOCK_SIZE,bool final=false) + { + byte[] outbytes = new byte[PSVIMGConstants.SHA256_BLOCK_SIZE]; + shaCtx.BlockUpdate(blockData, 0x00, length); + Sha256Digest shaTmp = (Sha256Digest)shaCtx.Copy(); + shaTmp.DoFinal(outbytes,0x00); + return outbytes; + } + + private void finishBlock(bool final = false) + { + int len = Convert.ToInt32(blockStream.Position); + byte[] shaBytes = shaBlock(len, final); + blockStream.Write(shaBytes, 0x00, PSVIMGConstants.SHA256_BLOCK_SIZE); + len += PSVIMGConstants.SHA256_BLOCK_SIZE; + + //Get next IV + byte[] encryptedBlock = aes_cbc_encrypt(blockData, IV, KEY, len); + for (int i = 0; i < IV.Length; i++) + { + int encBlockOffset = (encryptedBlock.Length - IV.Length)+i; + IV[i] = encryptedBlock[encBlockOffset]; + } + + mainStream.Write(encryptedBlock, 0x00, encryptedBlock.Length); + totalBytes += encryptedBlock.Length; + + blockStream.Dispose(); + } + + private int remainingBlockSize() + { + return Convert.ToInt32((PSVIMGConstants.PSVIMG_BLOCK_SIZE - blockStream.Position)); + } + + private void writeBlock(byte[] data, bool update=false) + { + long dLen = data.Length; + long writeTotal = 0; + while (dLen > 0) + { + int remaining = remainingBlockSize(); + + if (dLen > remaining) + { + byte[] dataRemains = new byte[remaining]; + Array.Copy(data, writeTotal, dataRemains, 0, remaining); + blockStream.Write(dataRemains, 0x00, remaining); + + writeTotal += remaining; + dLen -= remaining; + + + finishBlock(); + startNewBlock(); + if (update) + { + blocksWritten += 1; + } + } + else + { + byte[] dataRemains = new byte[dLen]; + Array.Copy(data, writeTotal, dataRemains, 0, dLen); + blockStream.Write(dataRemains, 0x00, Convert.ToInt32(dLen)); + + writeTotal += dLen; + dLen -= dLen; + } + } + } + private byte[] getPadding(long size) + { + using (MemoryStream ms = new MemoryStream()) + { + long paddingSize = PSVIMGPadding.GetPadding(size); + if(paddingSize != 0) + { + writePadding(ms, 0x2B, paddingSize-PSVIMGConstants.PSVIMG_PADDING_END.Length); + writeString(ms, PSVIMGConstants.PSVIMG_PADDING_END); + } + ms.Seek(0x00, SeekOrigin.Begin); + return ms.ToArray(); + } + } + + private byte[] getTailer() + { + using (MemoryStream ms = new MemoryStream()) + { + writeUInt64(ms, 0x00); + writePadding(ms, 0x7a, 1004); + writeString(ms, PSVIMGConstants.PSVIMG_TAILOR_END); + + ms.Seek(0x00, SeekOrigin.Begin); + return ms.ToArray(); + } + } + + private void writeStream(Stream dst) + { + while(dst.Position < dst.Length) + { + byte[] work_buf; + Int64 bytes_remain = (dst.Length - dst.Position); + if (bytes_remain > 0x33554432) + { + work_buf = new byte[0x33554432]; + } + else + { + work_buf = new byte[bytes_remain]; + } + dst.Read(work_buf, 0x00, work_buf.Length); + writeBlock(work_buf, true); + } + } + + private byte[] getFooter() + { + using (MemoryStream ms = new MemoryStream()) + { + totalBytes += 0x10; //number of bytes used by this footer. + + writeInt32(ms, 0x00); // int padding (idk wht this is) + writeUInt32(ms, 0x00); + writeInt64(ms, totalBytes); + ms.Seek(0x00, SeekOrigin.Begin); + return aes_cbc_encrypt(ms.ToArray(), IV, KEY); + } + + } + + public void AddFileAsync(string FilePath, string ParentPath, string PathRel) + { + finished = false; + new Thread(() => + { + long sz = Convert.ToInt64(sceIoStat(FilePath).Size); + writeBlock(getHeader(FilePath, ParentPath, PathRel)); + using (FileStream fs = File.OpenRead(FilePath)) + { + writeStream(fs); + } + writeBlock(getPadding(sz)); + writeBlock(getTailer()); + contentSize += sz; + finished = true; + }).Start(); + + } + public void AddFile(string FilePath, string ParentPath, string PathRel) + { + + long sz = Convert.ToInt64(sceIoStat(FilePath).Size); + writeBlock(getHeader(FilePath, ParentPath, PathRel)); + using (FileStream fs = File.OpenRead(FilePath)) + { + writeStream(fs); + } + writeBlock(getPadding(sz)); + writeBlock(getTailer()); + contentSize += sz; + } + + public void AddDir(string DirPath, string ParentPath, string PathRel) + { + writeBlock(getHeader(DirPath, ParentPath, PathRel)); + writeBlock(getPadding(0)); + writeBlock(getTailer()); + } + public long Finish() + { + finishBlock(true); + byte[] footer = getFooter(); + mainStream.Write(footer, 0x00, footer.Length); + + blockStream.Dispose(); + mainStream.Dispose(); + return contentSize; + } + + + public PSVIMGBuilder(Stream dst, byte[] Key) + { + totalBytes = 0; + contentSize = 0; + shaCtx = new Sha256Digest(); + mainStream = dst; + KEY = Key; + + rnd.NextBytes(IV); + IV = aes_ecb_encrypt(IV, Key); + + mainStream.Write(IV, 0x00, IV.Length); + totalBytes += IV.Length; + + startNewBlock(); + } + } +} diff --git a/CHOVY-TRANSFER/PSVIMGStructs.cs b/CHOVY-TRANSFER/PSVIMGStructs.cs new file mode 100644 index 0000000..3f67c05 --- /dev/null +++ b/CHOVY-TRANSFER/PSVIMGStructs.cs @@ -0,0 +1,212 @@ +using System; + +namespace PSVIMGTOOLS +{ + + internal class PSVIMGConstants + { + public const int AES_BLOCK_SIZE = 0x10; + public const int SHA256_BLOCK_SIZE = 0x20; + public const int PSVIMG_BLOCK_SIZE = 0x8000; + public const int PSVIMG_ENTRY_ALIGN = 0x400; + + public const string PSVIMG_HEADER_END = "EndOfHeader\n"; + public const string PSVIMG_TAILOR_END = "EndOfTailer\n"; + public const string PSVIMG_PADDING_END = "\n"; + + public const int FULL_PSVIMG_SIZE = PSVIMG_BLOCK_SIZE + SHA256_BLOCK_SIZE; + } + + internal class StringReader + { + internal static string ReadUntilTerminator(byte[] StringBytes) + { + string str = ""; + foreach (byte sByte in StringBytes) + { + if (sByte != 0x00) + { + str += (char)sByte; + } + else + { + return str; + } + } + return str; + } + } + + internal class SceDateTime + { + public UInt16 Year; + public UInt16 Month; + public UInt16 Day; + public UInt16 Hour; + public UInt16 Minute; + public UInt16 Second; + public UInt32 Microsecond; + + public SceDateTime() + { + + } + } + + internal class SceIoStat + { + public enum Modes{ + /** Format bits mask */ + FormatBits = 0xF000, + /** Symbolic link */ + SymbLink = 0x4000, + /** Directory */ + Directory = 0x1000, + /** Regular file */ + File = 0x2000, + + /** Set UID */ + SetUid = 0x0800, + /** Set GID */ + SetGid = 0x0400, + /** Sticky */ + Sticky = 0x0200, + + /** Others access rights mask */ + OthersAcesssMask = 0x01C0, + /** Others read permission */ + OthersRead = 0x0100, + /** Others write permission */ + OthersWrite = 0x0080, + /** Others execute permission */ + OthersExecute = 0x0040, + + /** Group access rights mask */ + GroupAcessMask = 0x0038, + /** Group read permission */ + GroupRead = 0x0020, + /** Group write permission */ + GroupWrite = 0x0010, + /** Group execute permission */ + GroupExecute = 0x0008, + + /** User access rights mask */ + UserAcessMask = 0x0007, + /** User read permission */ + UserRead = 0x0004, + /** User write permission */ + UserWrite = 0x0002, + /** User execute permission */ + UserExecute = 0x0001, + }; + public enum AttributesEnum + { + /** Format mask */ + FormatMask = 0x0038, // Format mask + /** Symlink */ + SymbLink = 0x0008, // Symbolic link + /** Directory */ + Directory = 0x0010, // Directory + /** Regular file */ + File = 0x0020, // Regular file + + /** Hidden read permission */ + Read = 0x0004, // read + /** Hidden write permission */ + Write = 0x0002, // write + /** Hidden execute permission */ + Execute = 0x0001, // execute + }; + + public Modes Mode; + public AttributesEnum Attributes; + /** Size of the file in bytes. */ + public UInt64 Size; + /** Creation time. */ + public SceDateTime CreationTime; + /** Access time. */ + public SceDateTime AccessTime; + /** Modification time. */ + public SceDateTime ModificaionTime; + /** Device-specific data. */ + public UInt32[] Private = new UInt32[6]; + public SceIoStat() + { + for(int i = 0; i < Private.Length; i++) + { + Private[i] = 0; + } + } + }; + + internal class PsvImgTailer + { + public UInt64 Flags; + public Byte[] Padding = new Byte[1004]; + public Byte[] bEnd = new Byte[12]; + + public String End + { + get + { + return StringReader.ReadUntilTerminator(bEnd); + } + } + } + internal class PSVIMGPadding + { + public static long GetPadding(long size) + { + long padding; + if ((size & (PSVIMGConstants.PSVIMG_ENTRY_ALIGN - 1)) >= 1) + { + padding = (PSVIMGConstants.PSVIMG_ENTRY_ALIGN - (size & (PSVIMGConstants.PSVIMG_ENTRY_ALIGN - 1))); + } + else + { + padding = 0; + } + return padding; + } + } + + internal class PsvImgHeader + { + public UInt64 SysTime; + public UInt64 Flags; + public SceIoStat Statistics; + public Byte[] bParentPath = new Byte[256]; + public UInt32 unk_16C; // set to 1 + public Byte[] bPath = new Byte[256]; + public Byte[] Padding = new Byte[904]; + public Byte[] bEnd = new Byte[12]; + + public String Path + { + get + { + return StringReader.ReadUntilTerminator(bPath); + } + } + + public String End + { + get + { + return StringReader.ReadUntilTerminator(bEnd); + } + } + + public String ParentPath + { + get + { + return StringReader.ReadUntilTerminator(bParentPath); + } + } + public PsvImgHeader() + { + + } + } +} diff --git a/CHOVY-TRANSFER/PSVMDBuilder.cs b/CHOVY-TRANSFER/PSVMDBuilder.cs new file mode 100644 index 0000000..fca25ae --- /dev/null +++ b/CHOVY-TRANSFER/PSVMDBuilder.cs @@ -0,0 +1,208 @@ +using Ionic.Zlib; +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; +namespace PSVIMGTOOLS +{ + class PSVMDBuilder + { + private static void memset(byte[] buf, byte content, long length) + { + for (int i = 0; i < length; i++) + { + buf[i] = content; + } + } + + private static void writeUInt64(Stream dst, UInt64 value) + { + byte[] ValueBytes = BitConverter.GetBytes(value); + dst.Write(ValueBytes, 0x00, 0x8); + } + private static void writeInt64(Stream dst, Int64 value) + { + byte[] ValueBytes = BitConverter.GetBytes(value); + dst.Write(ValueBytes, 0x00, 0x8); + } + private static void writeUInt16(Stream dst, UInt16 value) + { + byte[] ValueBytes = BitConverter.GetBytes(value); + dst.Write(ValueBytes, 0x00, 0x2); + } + private static void writeInt16(Stream dst, Int16 value) + { + byte[] ValueBytes = BitConverter.GetBytes(value); + dst.Write(ValueBytes, 0x00, 0x2); + } + + private static void writeInt32(Stream dst, Int32 value) + { + byte[] ValueBytes = BitConverter.GetBytes(value); + dst.Write(ValueBytes, 0x00, 0x4); + } + private static void writeUInt32(Stream dst, UInt32 value) + { + byte[] ValueBytes = BitConverter.GetBytes(value); + dst.Write(ValueBytes, 0x00, 0x4); + } + + + private static void writeString(Stream dst, string str, int len = -1) + { + if (len < 0) + { + len = str.Length; + } + + byte[] StrBytes = Encoding.UTF8.GetBytes(str); + dst.Write(StrBytes, 0x00, len); + } + + private static void writePadding(Stream dst, byte paddingByte, long paddingLen) + { + byte[] paddingData = new byte[paddingLen]; + memset(paddingData, paddingByte, paddingLen); + dst.Write(paddingData, 0x00, paddingData.Length); + } + private static void writeStringWithPadding(Stream dst, string str, int padSize, byte padByte = 0x78) + { + int StrLen = str.Length; + if (StrLen > padSize) + { + StrLen = padSize; + } + + int PaddingLen = (padSize - StrLen) - 1; + writeString(dst, str, StrLen); + dst.WriteByte(0x00); + writePadding(dst, padByte, PaddingLen); + } + + private static byte[] aes_ecb_decrypt(byte[] cipherText, byte[] KEY, int size = -1) + { + if (size < 0) + { + size = cipherText.Length; + } + + MemoryStream ms = new MemoryStream(); + + Aes alg = Aes.Create(); + alg.Mode = CipherMode.ECB; + alg.Padding = PaddingMode.None; + alg.KeySize = 256; + alg.BlockSize = 128; + alg.Key = KEY; + CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write); + cs.Write(cipherText, 0, size); + cs.Close(); + byte[] plainText = ms.ToArray(); + return plainText; + } + + private static byte[] aes_cbc_decrypt(byte[] cipherData, byte[] IV, byte[] Key) + { + MemoryStream ms = new MemoryStream(); + Aes alg = Aes.Create(); + alg.Mode = CipherMode.CBC; + alg.Padding = PaddingMode.None; + alg.KeySize = 256; + alg.BlockSize = 128; + alg.Key = Key; + alg.IV = IV; + CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write); + cs.Write(cipherData, 0, cipherData.Length); + cs.Close(); + byte[] decryptedData = ms.ToArray(); + return decryptedData; + } + private static byte[] aes_cbc_encrypt(byte[] plainText, byte[] IV, byte[] KEY, int size = -1) + { + if (size < 0) + { + size = plainText.Length; + } + + MemoryStream ms = new MemoryStream(); + + Aes alg = Aes.Create(); + alg.Mode = CipherMode.CBC; + alg.Padding = PaddingMode.None; + alg.KeySize = 256; + alg.BlockSize = 128; + alg.Key = KEY; + alg.IV = IV; + CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write); + cs.Write(plainText, 0, size); + cs.Close(); + byte[] cipherText = ms.ToArray(); + return cipherText; + } + + + public static void CreatePsvmd(Stream OutputStream, Stream EncryptedPsvimg, long ContentSize, string BackupType,byte[] Key) + { + byte[] IV = new byte[PSVIMGConstants.AES_BLOCK_SIZE]; + EncryptedPsvimg.Seek(0x00, SeekOrigin.Begin); + EncryptedPsvimg.Read(IV, 0x00, IV.Length); + IV = aes_ecb_decrypt(IV, Key); + MemoryStream ms = new MemoryStream(); + + writeUInt32(ms, 0xFEE1900D); // magic + writeUInt32(ms, 0x2); // type + writeUInt64(ms, 0x03000000); // fw ver + ms.Write(new byte[0x10], 0x00, 0x10); // PSID + writeStringWithPadding(ms, BackupType, 0x40, 0x00); //backup type + writeInt64(ms, EncryptedPsvimg.Length); // total size + writeUInt64(ms, 0x2); //version + writeInt64(ms, ContentSize); // content size + ms.Write(IV, 0x00, 0x10); // IV + writeUInt64(ms, 0x00); //ux0 info + writeUInt64(ms, 0x00); //ur0 info + writeUInt64(ms, 0x00); //unused 98 + writeUInt64(ms, 0x00); //unused A0 + writeUInt32(ms, 0x1); //add data + + ms.Seek(0x00, SeekOrigin.Begin); + byte[] psvMd = ms.ToArray(); + ms.Close(); + + ms = new MemoryStream(); + byte[] psvMdCompressed = ZlibStream.CompressBuffer(psvMd); + psvMdCompressed[0x1] = 0x9C; + ms.Write(psvMdCompressed, 0x00, psvMdCompressed.Length); + + SHA256 sha = SHA256.Create(); + byte[] shadata = sha.ComputeHash(psvMdCompressed); + ms.Write(shadata, 0x00, shadata.Length); + + int PaddingLen = Convert.ToInt32(PSVIMGConstants.AES_BLOCK_SIZE - (ms.Length & (PSVIMGConstants.AES_BLOCK_SIZE - 1))); + writePadding(ms, 0x00, PaddingLen); + + writeInt32(ms, PaddingLen); //Padding Length + writeUInt32(ms, 0x00); + writeInt64(ms, (ms.Length+0x8)+IV.Length); + ms.Seek(0x00, SeekOrigin.Begin); + byte[] toEncrypt = ms.ToArray(); + ms.Close(); + + byte[] EncryptedData = aes_cbc_encrypt(toEncrypt, IV, Key); + OutputStream.Write(IV, 0x00, IV.Length); + OutputStream.Write(EncryptedData, 0x00, EncryptedData.Length); + return; + } + + + public static byte[] DecryptPsvmd(Stream PsvMdFile, byte[] Key) + { + byte[] IV = new byte[PSVIMGConstants.AES_BLOCK_SIZE]; + PsvMdFile.Read(IV, 0x00, IV.Length); + byte[] remaining = new byte[PsvMdFile.Length - IV.Length]; + PsvMdFile.Read(remaining, 0x00, remaining.Length); + byte[] zlibCompressed = aes_cbc_decrypt(remaining, IV, Key); + return zlibCompressed; + // return ZlibStream.UncompressBuffer(zlibCompressed); + } + } +} diff --git a/CHOVY-TRANSFER/Program.cs b/CHOVY-TRANSFER/Program.cs new file mode 100644 index 0000000..f6d2c57 --- /dev/null +++ b/CHOVY-TRANSFER/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace CHOVY_TRANSFER +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new CHOVYTRANSFER()); + } + } +} diff --git a/CHOVY-TRANSFER/Properties/AssemblyInfo.cs b/CHOVY-TRANSFER/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..89b2172 --- /dev/null +++ b/CHOVY-TRANSFER/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("CHOVY-TRANSFER")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("CHOVY-TRANSFER")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("b4cad2c0-ba54-46b6-a8d0-43a9c2390d3c")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/CHOVY-TRANSFER/Properties/Resources.Designer.cs b/CHOVY-TRANSFER/Properties/Resources.Designer.cs new file mode 100644 index 0000000..d2bd39e --- /dev/null +++ b/CHOVY-TRANSFER/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace CHOVY_TRANSFER.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CHOVY_TRANSFER.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap chovytrans { + get { + object obj = ResourceManager.GetObject("chovytrans", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/CHOVY-TRANSFER/Properties/Resources.resx b/CHOVY-TRANSFER/Properties/Resources.resx new file mode 100644 index 0000000..2d0fb06 --- /dev/null +++ b/CHOVY-TRANSFER/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\chovytrans.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/CHOVY-TRANSFER/Properties/Settings.Designer.cs b/CHOVY-TRANSFER/Properties/Settings.Designer.cs new file mode 100644 index 0000000..24a2001 --- /dev/null +++ b/CHOVY-TRANSFER/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace CHOVY_TRANSFER.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.0.1.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/CHOVY-TRANSFER/Properties/Settings.settings b/CHOVY-TRANSFER/Properties/Settings.settings new file mode 100644 index 0000000..abf36c5 --- /dev/null +++ b/CHOVY-TRANSFER/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/CHOVY-TRANSFER/chovy-trans.ico b/CHOVY-TRANSFER/chovy-trans.ico new file mode 100644 index 0000000..ea97ee1 Binary files /dev/null and b/CHOVY-TRANSFER/chovy-trans.ico differ diff --git a/CHOVY-TRANSFER/chovytrans.gif b/CHOVY-TRANSFER/chovytrans.gif new file mode 100644 index 0000000..2813a6d Binary files /dev/null and b/CHOVY-TRANSFER/chovytrans.gif differ diff --git a/CHOVY-TRANSFER/cmakeys.cs b/CHOVY-TRANSFER/cmakeys.cs new file mode 100644 index 0000000..31a3b9c --- /dev/null +++ b/CHOVY-TRANSFER/cmakeys.cs @@ -0,0 +1,67 @@ +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; + +namespace KeyDerivation +{ + class CmaKeys + { + static Byte[] Passphrase = Encoding.ASCII.GetBytes("Sri Jayewardenepura Kotte"); + static Byte[] Key = { 0xA9, 0xFA, 0x5A, 0x62, 0x79, 0x9F, 0xCC, 0x4C, 0x72, 0x6B, 0x4E, 0x2C, 0xE3, 0x50, 0x6D, 0x38 }; + + public static string GenerateKeyStr(string Aid) + { + try + { + Int64 longlong = Convert.ToInt64(Aid, 16); + + byte[] AidBytes = BitConverter.GetBytes(longlong); + Array.Reverse(AidBytes); + + byte[] DerivedKey = CmaKeys.GenerateKey(AidBytes); + + + return BitConverter.ToString(DerivedKey).Replace("-", ""); + } + catch (Exception) + { + return "INVALID_AID"; + } + } + public static byte[] GenerateKey(byte[] Aid) + { + var ms = new MemoryStream(); + ms.Write(Aid, 0, Aid.Length); + ms.Write(Passphrase, 0, Passphrase.Length); + Byte[] DerviedKey = ms.ToArray(); + ms.Dispose(); + + SHA256 sha = SHA256.Create(); + DerviedKey = sha.ComputeHash(DerviedKey); + sha.Dispose(); + + DerviedKey = Decrypt(DerviedKey, Key); + + return DerviedKey; + } + + private static byte[] Decrypt(byte[] cipherData, + byte[] Key) + { + MemoryStream ms = new MemoryStream(); + Aes alg = Aes.Create(); + alg.Mode = CipherMode.ECB; + alg.Padding = PaddingMode.None; + alg.KeySize = 128; + alg.Key = Key; + CryptoStream cs = new CryptoStream(ms, + alg.CreateDecryptor(), CryptoStreamMode.Write); + cs.Write(cipherData, 0, cipherData.Length); + cs.Close(); + byte[] decryptedData = ms.ToArray(); + return decryptedData; + } + + } +} \ No newline at end of file diff --git a/CHOVY-TRANSFER/packages.config b/CHOVY-TRANSFER/packages.config new file mode 100644 index 0000000..5e69641 --- /dev/null +++ b/CHOVY-TRANSFER/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/CHOVY-TRANSFER/param.cs b/CHOVY-TRANSFER/param.cs new file mode 100644 index 0000000..d20730d --- /dev/null +++ b/CHOVY-TRANSFER/param.cs @@ -0,0 +1,569 @@ +/* Copyright (c) 2015 - 2018 TheDarkporgramer +* +* This was originally done by Jappi88 (Jappi88 at Gmail dot com) https://github.com/Jappi88 +* All modifications have been TheDarkporgramer (save sfo ext ext ) https://github.com/xXxTheDarkprogramerxXx +* +* This(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 acknowledge in the product documentation is 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. +* +* *Contact must be made to discuses permission and terms. +*/ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Linq; + +namespace Param_SFO +{ + public class PARAM_SFO + { + #region << Enums >> + public enum DataTypes : uint + { + PSN_Game = 18248, + GameData = 0x4744, + SaveData = 0x5344, + AppPhoto = 0x4150, + AppMusic = 0x414D, + AppVideo = 0x4156, + BroadCastVideo = 0x4256, + AppleTV = 4154, + WebTV = 5754, + CellBE = 0x4342, + Home = 0x484D, + StoreFronted = 0x5346, + HDDGame = 0x4847, + DiscGame = 0x4447, + AutoInstallRoot = 0x4152, + DiscPackage = 0x4450, + ExtraRoot = 0x5852, + VideoRoot = 0x5652, + ThemeRoot = 0x5452, + DiscMovie = 0x444D, + Game_Digital_Application = 0x4081AC0,//GD + PS4_Game_Application_Patch = 28775, + Additional_Content = 25441,//PSvita PS4 + GameContent = 25447,//PSVITA + Blu_Ray_Disc = 25698,//PS4 + None + } + + public enum FMT : ushort + { + UTF_8 = 0x0004, + ASCII = 0x0402, + Utf8Null = 0x0204, + UINT32 = 0x0404, + } + + #endregion << Enums >> + + #region << Vars>> + public List Tables { get; set; } + + #endregion << Vars>> + + #region << Example Of Calling Functions >> + //ypu can use this as SFO.Atribute + public string Attribute + { + get + { + if (Tables == null) + return ""; + foreach (Table t in Tables) + { + if (t.Name == "ATTRIBUTE") + return t.Value; + } + return ""; + } + } + + public DataTypes DataType + { + get + { + if (Tables == null) + return DataTypes.None; + foreach (Table t in Tables) + if (t.Name == "CATEGORY") + return ((DataTypes)BitConverter.ToUInt16(Encoding.UTF8.GetBytes(t.Value), 0)); + return DataTypes.None; + } + } + + public string APP_VER + { + get + { + if (Tables == null) + return ""; + foreach (Table t in Tables) + { + if (t.Name == "APP_VER") + return t.Value; + } + return ""; + } + } + + public string Detail + { + get + { + if (Tables == null) + return ""; + foreach (Table t in Tables) + if (t.Name == "DETAIL") + return t.Value; + return ""; + } + } + + public string ContentID + { + get + { + if (Tables == null) + return ""; + foreach (Table t in Tables) + if (t.Name == "CONTENT_ID") + return t.Value; + return ""; + } + } + + public string GetValue(string tagName) + { + foreach (Table t in Tables) + if (t.Name == tagName) + return t.Value; + return ""; + } + public string TITLEID + { + get + { + if (Tables == null) + return ""; + foreach (Table t in Tables) + if (t.Name == "TITLE_ID") + return t.Value; + return ""; + } + } + + public string TitleID + { + get + { + string name = TITLEID; + if (name == "") + return ""; + return name.Split('-')[0]; + } + } + + public string Title + { + get + { + if (Tables == null) + return ""; + foreach (Table t in Tables) + if (t.Name == "TITLE") + return t.Value; + return ""; + } + } + + public string Category + { + get + { + if (Tables == null) + return ""; + foreach (Table t in Tables) + if (t.Name == "CATEGORY") + return t.Value; + return ""; + } + } + + public enum Playstation + { + ps3 = 0, + psvita = 1, + ps4 = 2, + psp = 3, + unknown = 4,//there will be a time i no longer support the scene this will be for ps5+ most probabbly + } + + public Playstation PlaystationVersion + { + get + { + if (Tables == null) + return Playstation.unknown; + foreach (Table t in Tables) + { + if (t.Name == "PS3_SYSTEM_VER") + return Playstation.ps3;//this is the unique offset for ps3 + if (t.Name == "PSP2_SYSTEM_VER") + { + return Playstation.psvita;//this is the only flag that tells us its a psvita + } + if (t.Name == "PSP_SYSTEM_VER") + { + return Playstation.psp;//this is how we know its a psp + } + if (t.Name == "SYSTEM_VER")//i believe this to be only ps4 + { + return Playstation.ps4; + } + } + return Playstation.unknown; + } + } + + + #endregion << Example Of Calling Functions >> + + #region Param.SFO Struct + + public struct Header + { + public static byte[] Magic = { 0, 0x50, 0x53, 0x46 }; + public static byte[] version = { 01, 01, 0, 0 }; + public static uint KeyTableStart = 0; + public static uint DataTableStart = 0; + public static uint IndexTableEntries = 0; + + private static byte[] Buffer + { + get + { + var header = new byte[20]; + Array.Copy(Magic, 0, header, 0, 4); + Array.Copy(version, 0, header, 4, 4); + Array.Copy(BitConverter.GetBytes(KeyTableStart), 0, header, 8, 4); + Array.Copy(BitConverter.GetBytes(DataTableStart), 0, header, 12, 4); + Array.Copy(BitConverter.GetBytes(IndexTableEntries), 0, header, 16, 4); + return header; + } + } + + public static void Read(BinaryReader input) + { + input.BaseStream.Seek(0, SeekOrigin.Begin); + input.Read(Magic, 0, 4); + input.Read(version, 0, 4); + KeyTableStart = input.ReadUInt32(); + DataTableStart = input.ReadUInt32(); + IndexTableEntries = input.ReadUInt32(); + } + + } + [Serializable] + public struct Table : IComparable + { + public index_table Indextable; + public string Name; + public string Value; + public int index; + + public byte[] NameBuffer + { + get + { + var buffer = new byte[Name.Length + 1]; + Array.Copy(Encoding.UTF8.GetBytes(Name), 0, buffer, 0, Encoding.UTF8.GetBytes(Name).Length); + return buffer; + } + } + + public byte[] ValueBuffer + { + get + { + byte[] buffer; + switch (Indextable.param_data_fmt) + { + case FMT.ASCII: + buffer = new byte[Indextable.param_data_max_len]; + Array.Copy(Encoding.ASCII.GetBytes(Value), 0, buffer, 0, Encoding.UTF8.GetBytes(Value).Length); + return buffer; + case FMT.UINT32: + return BitConverter.GetBytes(uint.Parse(Value)); + case FMT.UTF_8: + buffer = new byte[Indextable.param_data_max_len]; + Array.Copy(Encoding.UTF8.GetBytes(Value), 0, buffer, 0, Encoding.UTF8.GetBytes(Value).Length); + return buffer; + case FMT.Utf8Null: + buffer = new byte[Indextable.param_data_max_len]; + Array.Copy(Encoding.UTF8.GetBytes(Value), 0, buffer, 0, Encoding.UTF8.GetBytes(Value).Length);/*write the length of the array*/ + return buffer; + default: + return null; + } + } + } + + public int CompareTo(object obj) + { + throw new NotImplementedException(); + } + } + [Serializable] + public struct index_table + { + public FMT param_data_fmt; /* param_data data type */ + public uint param_data_len; /* param_data used bytes */ + public uint param_data_max_len; /* param_data total reserved bytes */ + public uint param_data_offset; /* param_data offset (relative to start offset of data_table) */ + public ushort param_key_offset; /* param_key offset (relative to start offset of key_table) */ + + + private byte[] Buffer + { + get + { + var data = new byte[16]; + Array.Copy(BitConverter.GetBytes(param_key_offset), 0, data, 0, 2); + Array.Copy(BitConverter.GetBytes(((ushort)param_data_fmt)), 0, data, 2, 2); + Array.Copy(BitConverter.GetBytes(param_data_len), 0, data, 4, 4); + Array.Copy(BitConverter.GetBytes(param_data_max_len), 0, data, 8, 4); + Array.Copy(BitConverter.GetBytes(param_data_offset), 0, data, 12, 4); + return data; + } + } + + public void Read(BinaryReader input) + { + param_key_offset = input.ReadUInt16(); + param_data_fmt = (FMT)input.ReadUInt16(); + param_data_len = input.ReadUInt32(); + param_data_max_len = input.ReadUInt32(); + param_data_offset = input.ReadUInt32(); + } + } + + [Serializable] + private enum DATA_TYPE : byte + { + BinaryData = 0, + Utf8Text = 2, + Si32Integer = 4 + } + + #endregion Param.SFO Struct + + #region << Methods >> + + + public PARAM_SFO() + { + + } + + public PARAM_SFO(string filepath) + { + Init(new FileStream(filepath, FileMode.Open, FileAccess.Read, FileShare.Read)); + } + + public PARAM_SFO(byte[] inputdata) + { + Init(new MemoryStream(inputdata)); + } + + public PARAM_SFO(Stream input) + { + Init(input); + } + + + /// + /// This is the SaveSFO Function for PS3/PS4/PSVita/And PSP no longer needed for Sony's CMD + /// + /// SFO That has been opened + /// Save Location + public void SaveSFO(PARAM_SFO psfo, string filename) + { + //we start by opening the stream to the file + using (var stream = File.Open(filename, FileMode.Create, FileAccess.Write, FileShare.Read)) + { + if (!stream.CanSeek) + throw new ArgumentException("Stream must be seekable");//throw this error we cant seek the stream + + var utf8 = new UTF8Encoding(false);//encoding + using (var writer = new BinaryWriter(stream, utf8))//start binary reader + { + + #region << Header Info (DevWiki) >> + /* + Header + * 0x00 0x04 magic PSF + 0x04 0x04 version 01 01 00 00 1.01 + 0x08 0x04 key_table_start 24 00 00 00 Absolute start offset of key_table = 0x24 + 0x0C 0x04 data_table_start 30 00 00 00 Absolute start offset of data_table = 0x30 + 0x10 0x04 tables_entries 01 00 00 00 Number of entries in index_table, key_table, and data_table = 1 + */ + + #endregion <
> + + //so lets start writing the info + writer.Write(Header.Magic);//write magic "\0PSF" + writer.Write(Header.version);//write version info this is mayjor and minor (01 01 00 00 1.01) + Header.KeyTableStart = 0x14 + Header.IndexTableEntries * 0x10;/*we can write all this lovely info from the tables back*/ + writer.Write(Header.KeyTableStart); + + Header.DataTableStart = Convert.ToUInt32(Header.KeyTableStart + Tables.Sum(i => i.Name.Length + 1));//needs to be Uint + if (Header.DataTableStart % 4 != 0) + Header.DataTableStart = (Header.DataTableStart / 4 + 1) * 4; + writer.Write(Header.DataTableStart); + Header.IndexTableEntries = Convert.ToUInt32(Tables.Count); + writer.Write(Header.IndexTableEntries); + + int lastKeyOffset = Convert.ToInt32(Header.KeyTableStart); + int lastValueOffset = Convert.ToInt32(Header.DataTableStart); + for (var i = 0; i < Tables.Count; i++) + { + var entry = Tables[i]; + + writer.BaseStream.Seek(0x14 + i * 0x10, SeekOrigin.Begin); + writer.Write((ushort)(lastKeyOffset - Header.KeyTableStart)); + + + writer.Write((ushort)entry.Indextable.param_data_fmt); + + writer.Write(entry.Indextable.param_data_len); + writer.Write(entry.Indextable.param_data_max_len); + writer.Write(lastValueOffset - Header.DataTableStart); + + writer.BaseStream.Seek(lastKeyOffset, SeekOrigin.Begin); + writer.Write(utf8.GetBytes(entry.Name)); + writer.Write((byte)0); + lastKeyOffset = (int)writer.BaseStream.Position; + + writer.BaseStream.Seek(lastValueOffset, SeekOrigin.Begin); + writer.Write(entry.ValueBuffer); + lastValueOffset = (int)writer.BaseStream.Position; + } + + //I'm doing this to just rewrite the first item (Some Cleanup will be needed) + //Or maybe not as when I checked this gives a 1 - 1 match with how the Sony tool works + //we need to rewrite that first item (PS4/PS3/PSV should be APP-VER) + lastKeyOffset = Convert.ToInt32(Header.KeyTableStart); + lastValueOffset = Convert.ToInt32(Header.DataTableStart); + + var tableentry = Tables[0]; + + writer.BaseStream.Seek(lastKeyOffset, SeekOrigin.Begin); + writer.Write(utf8.GetBytes(tableentry.Name)); + writer.Write((byte)0); + lastKeyOffset = (int)writer.BaseStream.Position; + + } + } + + } + + private string ReadValue(BinaryReader br, index_table table) + { + br.BaseStream.Position = ((Header.DataTableStart) + table.param_data_offset); + switch (table.param_data_fmt) + { + case FMT.ASCII: + //return Encoding.GetEncoding(1252).GetString(br.ReadBytes((int) table.param_data_max_len)).Replace("\0", ""); + return Encoding.UTF8.GetString(br.ReadBytes((int)table.param_data_max_len)).Replace("\0", ""); + case FMT.UINT32: + return br.ReadUInt32().ToString(); + case FMT.UTF_8: + return Encoding.UTF8.GetString(br.ReadBytes((int)table.param_data_max_len)).Replace("\0", ""); + case FMT.Utf8Null: + return Encoding.UTF8.GetString(br.ReadBytes((int)table.param_data_max_len)).Replace("\0", ""); + default: + return null; + } + } + + private string ReadValueSpecialChars(BinaryReader br, index_table table) + { + br.BaseStream.Position = ((Header.DataTableStart) + table.param_data_offset); + switch (table.param_data_fmt) + { + case FMT.ASCII: + return Encoding.UTF8.GetString(br.ReadBytes((int)table.param_data_max_len)).Replace("\0", ""); + case FMT.UINT32: + return br.ReadUInt32().ToString(); + case FMT.UTF_8: + return Encoding.UTF8.GetString(br.ReadBytes((int)table.param_data_max_len)).Replace("\0", ""); + default: + return null; + } + } + + private string ReadName(BinaryReader br, index_table table) + { + br.BaseStream.Position = (Header.KeyTableStart + table.param_key_offset); + string name = ""; + while (((byte)br.PeekChar()) != 0) + name += br.ReadChar(); + br.BaseStream.Position++; + return name; + } + + /// + /// Start Reading the Parameter file + /// + /// Input Stream + private void Init(Stream input) + { + using (var br = new BinaryReader(input)) + { + Header.Read(br); + var tables = new List(); + for (int i = 0; i < Header.IndexTableEntries; i++) + { + var t = new index_table(); + t.Read(br); + tables.Add(t); + } + var xtables = new List
(); + int count = 0; + foreach (index_table t in tables) + { + var x = new Table(); + x.index = count; + x.Indextable = t; + x.Name = ReadName(br, t); + x.Value = ReadValue(br, t); + count++; + xtables.Add(x); + } + Tables = xtables; + br.Close(); + } + } + + + #endregion << Methods >> + + } +} \ No newline at end of file diff --git a/chovy-trans.ico b/chovy-trans.ico new file mode 100644 index 0000000..ea97ee1 Binary files /dev/null and b/chovy-trans.ico differ diff --git a/packages/BouncyCastle.1.8.5/BouncyCastle.1.8.5.nupkg b/packages/BouncyCastle.1.8.5/BouncyCastle.1.8.5.nupkg new file mode 100644 index 0000000..f6d7c2a Binary files /dev/null and b/packages/BouncyCastle.1.8.5/BouncyCastle.1.8.5.nupkg differ diff --git a/packages/BouncyCastle.1.8.5/README.md b/packages/BouncyCastle.1.8.5/README.md new file mode 100644 index 0000000..270d9cc --- /dev/null +++ b/packages/BouncyCastle.1.8.5/README.md @@ -0,0 +1,30 @@ +# The Bouncy Castle Crypto Package For C Sharp + +The Bouncy Castle Crypto package is a C\# implementation of cryptographic algorithms and protocols, it was developed by the Legion of the Bouncy Castle, a registered Australian Charity, with a little help! The Legion, and the latest goings on with this package, can be found at [http://www.bouncycastle.org](http://www.bouncycastle.org). In addition to providing basic cryptography algorithms, the package also provides support for CMS, TSP, X.509 certificate generation and a variety of other standards such as OpenPGP. + +The Legion also gratefully acknowledges the contributions made to this package by others (see [here](http://www.bouncycastle.org/csharp/contributors.html) for the current list). If you would like to contribute to our efforts please feel free to get in touch with us or visit our [donations page](https://www.bouncycastle.org/donate), sponsor some specific work, or purchase a support contract through [Crypto Workshop](http://www.cryptoworkshop.com). + +Except where otherwise stated, this software is distributed under a license based on the MIT X Consortium license. To view the license, [see here](http://www.bouncycastle.org/licence.html). The OpenPGP library also includes a modified BZIP2 library which is licensed under the [Apache Software License, Version 2.0](http://www.apache.org/licenses/). + +**Note**: this source tree is not the FIPS version of the APIs - if you are interested in our FIPS version please contact us directly at [office@bouncycastle.org](mailto:office@bouncycastle.org). + +## Mailing Lists + +For those who are interested, there are 2 mailing lists for participation in this project. To subscribe use the links below and include the word subscribe in the message body. (To unsubscribe, replace **subscribe** with **unsubscribe** in the message body) + +* [announce-crypto-csharp-request@bouncycastle.org](mailto:announce-crypto-csharp-request@bouncycastle.org) + This mailing list is for new release announcements only, general subscribers cannot post to it. +* [dev-crypto-csharp-request@bouncycastle.org](mailto:dev-crypto-csharp-request@bouncycastle.org) + This mailing list is for discussion of development of the package. This includes bugs, comments, requests for enhancements, questions about use or operation. + +**NOTE:**You need to be subscribed to send mail to the above mailing list. + +## Feedback + +If you want to provide feedback directly to the members of **The Legion** then please use [feedback-crypto@bouncycastle.org](mailto:feedback-crypto@bouncycastle.org), if you want to help this project survive please consider [donating](https://www.bouncycastle.org/donate). + +For bug reporting/requests you can report issues here on github, via feedback-crypto if required, and we also have a [Jira issue tracker](http://www.bouncycastle.org/jira). We will accept pull requests based on this repository as well. + +## Finally + +Enjoy! diff --git a/packages/BouncyCastle.1.8.5/lib/BouncyCastle.Crypto.dll b/packages/BouncyCastle.1.8.5/lib/BouncyCastle.Crypto.dll new file mode 100644 index 0000000..05036dd Binary files /dev/null and b/packages/BouncyCastle.1.8.5/lib/BouncyCastle.Crypto.dll differ diff --git a/packages/DotNetZip.1.13.4/DotNetZip.1.13.4.nupkg b/packages/DotNetZip.1.13.4/DotNetZip.1.13.4.nupkg new file mode 100644 index 0000000..611052b Binary files /dev/null and b/packages/DotNetZip.1.13.4/DotNetZip.1.13.4.nupkg differ diff --git a/packages/DotNetZip.1.13.4/lib/net40/DotNetZip.dll b/packages/DotNetZip.1.13.4/lib/net40/DotNetZip.dll new file mode 100644 index 0000000..2b6455d Binary files /dev/null and b/packages/DotNetZip.1.13.4/lib/net40/DotNetZip.dll differ diff --git a/packages/DotNetZip.1.13.4/lib/net40/DotNetZip.pdb b/packages/DotNetZip.1.13.4/lib/net40/DotNetZip.pdb new file mode 100644 index 0000000..87522e7 Binary files /dev/null and b/packages/DotNetZip.1.13.4/lib/net40/DotNetZip.pdb differ diff --git a/packages/DotNetZip.1.13.4/lib/net40/DotNetZip.xml b/packages/DotNetZip.1.13.4/lib/net40/DotNetZip.xml new file mode 100644 index 0000000..bcb5bbf --- /dev/null +++ b/packages/DotNetZip.1.13.4/lib/net40/DotNetZip.xml @@ -0,0 +1,18529 @@ + + + + DotNetZip + + + + + Delivers the remaining bits, left-aligned, in a byte. + + + + This is valid only if NumRemainingBits is less than 8; + in other words it is valid only after a call to Flush(). + + + + + + Reset the BitWriter. + + + + This is useful when the BitWriter writes into a MemoryStream, and + is used by a BZip2Compressor, which itself is re-used for multiple + distinct data blocks. + + + + + + Write some number of bits from the given value, into the output. + + + + The nbits value should be a max of 25, for safety. For performance + reasons, this method does not check! + + + + + + Write a full 8-bit byte into the output. + + + + + Write four 8-bit bytes into the output. + + + + + Write all available byte-aligned bytes. + + + + This method writes no new output, but flushes any accumulated + bits. At completion, the accumulator may contain up to 7 + bits. + + + This is necessary when re-assembling output from N independent + compressors, one for each of N blocks. The output of any + particular compressor will in general have some fragment of a byte + remaining. This fragment needs to be accumulated into the + parent BZip2OutputStream. + + + + + + Writes all available bytes, and emits padding for the final byte as + necessary. This must be the last method invoked on an instance of + BitWriter. + + + + Knuth's increments seem to work better than Incerpi-Sedgewick here. + Possibly because the number of elems to sort is usually small, typically + <= 20. + + + + BZip2Compressor writes its compressed data out via a BitWriter. This + is necessary because BZip2 does byte shredding. + + + + + The number of uncompressed bytes being held in the buffer. + + + + I am thinking this may be useful in a Stream that uses this + compressor class. In the Close() method on the stream it could + check this value to see if anything has been written at all. You + may think the stream could easily track the number of bytes it + wrote, which would eliminate the need for this. But, there is the + case where the stream writes a complete block, and it is full, and + then writes no more. In that case the stream may want to check. + + + + + + Accept new bytes into the compressor data buffer + + + + This method does the first-level (cheap) run-length encoding, and + stores the encoded data into the rle block. + + + + + + Process one input byte into the block. + + + + + To "process" the byte means to do the run-length encoding. + There are 3 possible return values: + + 0 - the byte was not written, in other words, not + encoded into the block. This happens when the + byte b would require the start of a new run, and + the block has no more room for new runs. + + 1 - the byte was written, and the block is not full. + + 2 - the byte was written, and the block is full. + + + + 0 if the byte was not written, non-zero if written. + + + + Append one run to the output block. + + + + + This compressor does run-length-encoding before BWT and etc. This + method simply appends a run to the output block. The append always + succeeds. The return value indicates whether the block is full: + false (not full) implies that at least one additional run could be + processed. + + + true if the block is now full; otherwise false. + + + + Compress the data that has been placed (Run-length-encoded) into the + block. The compressed data goes into the CompressedBytes array. + + + + Side effects: 1. fills the CompressedBytes array. 2. sets the + AvailableBytesOut property. + + + + + This is the most hammered method of this class. + +

+ This is the version using unrolled loops. +

+
+ + Method "mainQSort3", file "blocksort.c", BZip2 1.0.2 + + + Array instance identical to sfmap, both are used only + temporarily and independently, so we do not need to allocate + additional memory. + + + + A read-only decorator stream that performs BZip2 decompression on Read. + + + + + Compressor State + + + + + Create a BZip2InputStream, wrapping it around the given input Stream. + + + + The input stream will be closed when the BZip2InputStream is closed. + + + The stream from which to read compressed data + + + + Create a BZip2InputStream with the given stream, and + specifying whether to leave the wrapped stream open when + the BZip2InputStream is closed. + + The stream from which to read compressed data + + Whether to leave the input stream open, when the BZip2InputStream closes. + + + + + This example reads a bzip2-compressed file, decompresses it, + and writes the decompressed data into a newly created file. + + + var fname = "logfile.log.bz2"; + using (var fs = File.OpenRead(fname)) + { + using (var decompressor = new Ionic.BZip2.BZip2InputStream(fs)) + { + var outFname = fname + ".decompressed"; + using (var output = File.Create(outFname)) + { + byte[] buffer = new byte[2048]; + int n; + while ((n = decompressor.Read(buffer, 0, buffer.Length)) > 0) + { + output.Write(buffer, 0, n); + } + } + } + } + + + + + + Read data from the stream. + + + + + To decompress a BZip2 data stream, create a BZip2InputStream, + providing a stream that reads compressed data. Then call Read() on + that BZip2InputStream, and the data read will be decompressed + as you read. + + + + A BZip2InputStream can be used only for Read(), not for Write(). + + + + 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 + + + + Read a single byte from the stream. + + the byte read from the stream, or -1 if EOF + + + + Indicates whether the stream can be read. + + + The return value depends on whether the captive stream supports reading. + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream can be written. + + + The return value depends on whether the captive stream supports writing. + + + + + Flush the stream. + + + + + Reading this property always throws a . + + + + + The position of the stream pointer. + + + + Setting this property always throws a . Reading will return the + total number of uncompressed bytes read in. + + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + this is irrelevant, since it will always throw! + irrelevant! + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + + + + Calling this method always throws a . + + this parameter is never used + this parameter is never used + this parameter is never used + + + + Dispose the stream. + + + indicates whether the Dispose method was invoked by user code. + + + + + Close the stream. + + + + + Read n bits from input, right justifying the result. + + + + For example, if you read 1 bit, the result is either 0 + or 1. + + + + The number of bits to read, always between 1 and 32. + + + + Called by createHuffmanDecodingTables() exclusively. + + + Called by recvDecodingTables() exclusively. + + + Freq table collected to save a pass over the data during + decompression. + + + Initializes the tt array. + + This method is called when the required length of the array is known. + I don't initialize it at construction time to avoid unneccessary + memory allocation when compressing small files. + + + + A write-only decorator stream that compresses data as it is + written using the BZip2 algorithm. + + + + + Constructs a new BZip2OutputStream, that sends its + compressed output to the given output stream. + + + + The destination stream, to which compressed output will be sent. + + + + + This example reads a file, then compresses it with bzip2 file, + and writes the compressed data into a newly created file. + + + var fname = "logfile.log"; + using (var fs = File.OpenRead(fname)) + { + var outFname = fname + ".bz2"; + using (var output = File.Create(outFname)) + { + using (var compressor = new Ionic.BZip2.BZip2OutputStream(output)) + { + byte[] buffer = new byte[2048]; + int n; + while ((n = fs.Read(buffer, 0, buffer.Length)) > 0) + { + compressor.Write(buffer, 0, n); + } + } + } + } + + + + + + Constructs a new BZip2OutputStream with specified blocksize. + + the destination stream. + + The blockSize in units of 100000 bytes. + The valid range is 1..9. + + + + + Constructs a new BZip2OutputStream. + + the destination stream. + + whether to leave the captive stream open upon closing this stream. + + + + + Constructs a new BZip2OutputStream with specified blocksize, + and explicitly specifies whether to leave the wrapped stream open. + + + the destination stream. + + The blockSize in units of 100000 bytes. + The valid range is 1..9. + + + whether to leave the captive stream open upon closing this stream. + + + + + Close the stream. + + + + This may or may not close the underlying stream. Check the + constructors that accept a bool value. + + + + + + Flush the stream. + + + + + The blocksize parameter specified at construction time. + + + + + Write data to the stream. + + + + + Use the BZip2OutputStream to compress data while writing: + create a BZip2OutputStream with a writable output stream. + Then call Write() on that BZip2OutputStream, providing + uncompressed data as input. The data sent to the output stream will + be the compressed form of the input data. + + + + A BZip2OutputStream can be used only for Write() not for Read(). + + + + + 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. + + + + Indicates whether the stream can be read. + + + The return value is always false. + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream can be written. + + + The return value should always be true, unless and until the + object is disposed and closed. + + + + + Reading this property always throws a . + + + + + The position of the stream pointer. + + + + Setting this property always throws a . Reading will return the + total number of uncompressed bytes written through. + + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + this is irrelevant, since it will always throw! + irrelevant! + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + + + + Calling this method always throws a . + + this parameter is never used + this parameter is never used + this parameter is never used + never returns anything; always throws + + + + A write-only decorator stream that compresses data as it is + written using the BZip2 algorithm. This stream compresses by + block using multiple threads. + + + This class performs BZIP2 compression through writing. For + more information on the BZIP2 algorithm, see + . + + + + This class is similar to , + except that this implementation uses an approach that employs multiple + worker threads to perform the compression. On a multi-cpu or multi-core + computer, the performance of this class can be significantly higher than + the single-threaded BZip2OutputStream, particularly for larger streams. + How large? Anything over 10mb is a good candidate for parallel + compression. + + + + The tradeoff is that this class uses more memory and more CPU than the + vanilla BZip2OutputStream. Also, for small files, the + ParallelBZip2OutputStream can be much slower than the vanilla + BZip2OutputStream, because of the overhead associated to using the + thread pool. + + + + + + + Constructs a new ParallelBZip2OutputStream, that sends its + compressed output to the given output stream. + + + + The destination stream, to which compressed output will be sent. + + + + + This example reads a file, then compresses it with bzip2 file, + and writes the compressed data into a newly created file. + + + var fname = "logfile.log"; + using (var fs = File.OpenRead(fname)) + { + var outFname = fname + ".bz2"; + using (var output = File.Create(outFname)) + { + using (var compressor = new Ionic.BZip2.ParallelBZip2OutputStream(output)) + { + byte[] buffer = new byte[2048]; + int n; + while ((n = fs.Read(buffer, 0, buffer.Length)) > 0) + { + compressor.Write(buffer, 0, n); + } + } + } + } + + + + + + Constructs a new ParallelBZip2OutputStream with specified blocksize. + + the destination stream. + + The blockSize in units of 100000 bytes. + The valid range is 1..9. + + + + + Constructs a new ParallelBZip2OutputStream. + + the destination stream. + + whether to leave the captive stream open upon closing this stream. + + + + + Constructs a new ParallelBZip2OutputStream with specified blocksize, + and explicitly specifies whether to leave the wrapped stream open. + + + the destination stream. + + The blockSize in units of 100000 bytes. + The valid range is 1..9. + + + whether to leave the captive stream open upon closing this stream. + + + + + The maximum number of concurrent compression worker threads to use. + + + + + This property sets an upper limit on the number of concurrent worker + threads to employ for compression. The implementation of this stream + employs multiple threads from the .NET thread pool, via + ThreadPool.QueueUserWorkItem(), to compress the incoming data by + block. As each block of data is compressed, this stream re-orders the + compressed blocks and writes them to the output stream. + + + + A higher number of workers enables a higher degree of + parallelism, which tends to increase the speed of compression on + multi-cpu computers. On the other hand, a higher number of buffer + pairs also implies a larger memory consumption, more active worker + threads, and a higher cpu utilization for any compression. This + property enables the application to limit its memory consumption and + CPU utilization behavior depending on requirements. + + + + By default, DotNetZip allocates 4 workers per CPU core, subject to the + upper limit specified in this property. For example, suppose the + application sets this property to 16. Then, on a machine with 2 + cores, DotNetZip will use 8 workers; that number does not exceed the + upper limit specified by this property, so the actual number of + workers used will be 4 * 2 = 8. On a machine with 4 cores, DotNetZip + will use 16 workers; again, the limit does not apply. On a machine + with 8 cores, DotNetZip will use 16 workers, because of the limit. + + + + For each compression "worker thread" that occurs in parallel, there is + up to 2mb of memory allocated, for buffering and processing. The + actual number depends on the property. + + + + CPU utilization will also go up with additional workers, because a + larger number of buffer pairs allows a larger number of background + threads to compress in parallel. If you find that parallel + compression is consuming too much memory or CPU, you can adjust this + value downward. + + + + The default value is 16. Different values may deliver better or + worse results, depending on your priorities and the dynamic + performance characteristics of your storage and compute resources. + + + + The application can set this value at any time, but it is effective + only before the first call to Write(), which is when the buffers are + allocated. + + + + + + Close the stream. + + + + This may or may not close the underlying stream. Check the + constructors that accept a bool value. + + + + + + Flush the stream. + + + + + The blocksize parameter specified at construction time. + + + + + Write data to the stream. + + + + + Use the ParallelBZip2OutputStream to compress data while + writing: create a ParallelBZip2OutputStream with a writable + output stream. Then call Write() on that + ParallelBZip2OutputStream, providing uncompressed data as + input. The data sent to the output stream will be the compressed + form of the input data. + + + + A ParallelBZip2OutputStream can be used only for + Write() not for Read(). + + + + + 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. + + + + Indicates whether the stream can be read. + + + The return value is always false. + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream can be written. + + + The return value depends on whether the captive stream supports writing. + + + + + Reading this property always throws a . + + + + + The position of the stream pointer. + + + + Setting this property always throws a . Reading will return the + total number of uncompressed bytes written through. + + + + + The total number of bytes written out by the stream. + + + This value is meaningful only after a call to Close(). + + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + this is irrelevant, since it will always throw! + irrelevant! + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + + + + Calling this method always throws a . + + this parameter is never used + this parameter is never used + this parameter is never used + never returns anything; always throws + + + + Returns the "random" number at a specific index. + + the index + the random number + + + + An enum that provides the different self-extractor flavors + + + + + A self-extracting zip archive that runs from the console or + command line. + + + + + A self-extracting zip archive that presents a graphical user + interface when it is executed. + + + + + The options for generating a self-extracting archive. + + + + + The type of SFX to create. + + + + + The command to run after extraction. + + + + + This is optional. Leave it empty (null in C# or Nothing in + VB) to run no command after extraction. + + + + If it is non-empty, the SFX will execute the command specified in this + string on the user's machine, and using the extract directory as the + working directory for the process, after unpacking the archive. The + program to execute can include a path, if you like. If you want to execute + a program that accepts arguments, specify the program name, followed by a + space, and then the arguments for the program, each separated by a space, + just as you would on a normal command line. Example: program.exe arg1 + arg2. The string prior to the first space will be taken as the + program name, and the string following the first space specifies the + arguments to the program. + + + + If you want to execute a program that has a space in the name or path of + the file, surround the program name in double-quotes. The first character + of the command line should be a double-quote character, and there must be + a matching double-quote following the end of the program file name. Any + optional arguments to the program follow that, separated by + spaces. Example: "c:\project files\program name.exe" arg1 arg2. + + + + If the flavor of the SFX is SelfExtractorFlavor.ConsoleApplication, + then the SFX starts a new process, using this string as the post-extract + command line. The SFX waits for the process to exit. The exit code of + the post-extract command line is returned as the exit code of the + command-line self-extractor exe. A non-zero exit code is typically used to + indicated a failure by the program. In the case of an SFX, a non-zero exit + code may indicate a failure during extraction, OR, it may indicate a + failure of the run-after-extract program if specified, OR, it may indicate + the run-after-extract program could not be fuond. There is no way to + distinguish these conditions from the calling shell, aside from parsing + the output of the SFX. If you have Quiet set to true, you may not + see error messages, if a problem occurs. + + + + If the flavor of the SFX is + SelfExtractorFlavor.WinFormsApplication, then the SFX starts a new + process, using this string as the post-extract command line, and using the + extract directory as the working directory for the process. The SFX does + not wait for the command to complete, and does not check the exit code of + the program. If the run-after-extract program cannot be fuond, a message + box is displayed indicating that fact. + + + + You can specify environment variables within this string, with a format like + %NAME%. The value of these variables will be expanded at the time + the SFX is run. Example: %WINDIR%\system32\xcopy.exe may expand at + runtime to c:\Windows\System32\xcopy.exe. + + + + By combining this with the RemoveUnpackedFilesAfterExecute + flag, you can create an SFX that extracts itself, runs a file that + was extracted, then deletes all the files that were extracted. If + you want it to run "invisibly" then set Flavor to + SelfExtractorFlavor.ConsoleApplication, and set Quiet + to true. The user running such an EXE will see a console window + appear, then disappear quickly. You may also want to specify the + default extract location, with DefaultExtractDirectory. + + + + If you set Flavor to + SelfExtractorFlavor.WinFormsApplication, and set Quiet to + true, then a GUI with progressbars is displayed, but it is + "non-interactive" - it accepts no input from the user. Instead the SFX + just automatically unpacks and exits. + + + + + + + The default extract directory the user will see when + running the self-extracting archive. + + + + + Passing null (or Nothing in VB) here will cause the Self Extractor to use + the the user's personal directory () for the default extract + location. + + + + This is only a default location. The actual extract location will be + settable on the command line when the SFX is executed. + + + + You can specify environment variables within this string, + with %NAME%. The value of these variables will be + expanded at the time the SFX is run. Example: + %USERPROFILE%\Documents\unpack may expand at runtime to + c:\users\melvin\Documents\unpack. + + + + + + The name of an .ico file in the filesystem to use for the application icon + for the generated SFX. + + + + + Normally, DotNetZip will embed an "zipped folder" icon into the generated + SFX. If you prefer to use a different icon, you can specify it here. It + should be a .ico file. This file is passed as the /win32icon + option to the csc.exe compiler when constructing the SFX file. + + + + + + + Whether the ConsoleApplication SFX will be quiet during extraction. + + + + + This option affects the way the generated SFX runs. By default it is + false. When you set it to true,... + + + + + Flavor + Behavior + + + + ConsoleApplication + no messages will be emitted during successful + operation. Double-clicking the SFX in Windows + Explorer or as an attachment in an email will cause a console + window to appear briefly, before it disappears. If you run the + ConsoleApplication SFX from the cmd.exe prompt, it runs as a + normal console app; by default, because it is quiet, it displays + no messages to the console. If you pass the -v+ command line + argument to the Console SFX when you run it, you will get verbose + messages to the console. + + + + + WinFormsApplication + the SFX extracts automatically when the application + is launched, with no additional user input. + + + + + + + When you set it to false,... + + + + + Flavor + Behavior + + + + ConsoleApplication + the extractor will emit a + message to the console for each entry extracted. + + When double-clicking to launch the SFX, the console window will + remain, and the SFX will emit a message for each file as it + extracts. The messages fly by quickly, they won't be easily + readable, unless the extracted files are fairly large. + + + + + + WinFormsApplication + the SFX presents a forms UI and allows the user to select + options before extracting. + + + + + + + + + + Specify what the self-extractor will do when extracting an entry + would overwrite an existing file. + + + + The default behavvior is to Throw. + + + + + + Whether to remove the files that have been unpacked, after executing the + PostExtractCommandLine. + + + + + If true, and if there is a + PostExtractCommandLine, and if the command runs successfully, + then the files that the SFX unpacked will be removed, afterwards. If + the command does not complete successfully (non-zero return code), + that is interpreted as a failure, and the extracted files will not be + removed. + + + + Setting this flag, and setting Flavor to + SelfExtractorFlavor.ConsoleApplication, and setting Quiet to + true, results in an SFX that extracts itself, runs a file that was + extracted, then deletes all the files that were extracted, with no + intervention by the user. You may also want to specify the default + extract location, with DefaultExtractDirectory. + + + + + + + The file version number to embed into the generated EXE. It will show up, for + example, during a mouseover in Windows Explorer. + + + + + + The product version to embed into the generated EXE. It will show up, for + example, during a mouseover in Windows Explorer. + + + + You can use any arbitrary string, but a human-readable version number is + recommended. For example "v1.2 alpha" or "v4.2 RC2". If you specify nothing, + then there is no product version embedded into the EXE. + + + + + + The copyright notice, if any, to embed into the generated EXE. + + + + It will show up, for example, while viewing properties of the file in + Windows Explorer. You can use any arbitrary string, but typically you + want something like "Copyright � Dino Chiesa 2011". + + + + + + The description to embed into the generated EXE. + + + + Use any arbitrary string. This text will be displayed during a + mouseover in Windows Explorer. If you specify nothing, then the string + "DotNetZip SFX Archive" is embedded into the EXE as the description. + + + + + + The product name to embed into the generated EXE. + + + + Use any arbitrary string. This text will be displayed + while viewing properties of the EXE file in + Windows Explorer. + + + + + + The title to display in the Window of a GUI SFX, while it extracts. + + + + + By default the title show in the GUI window of a self-extractor + is "DotNetZip Self-extractor (http://DotNetZip.codeplex.com/)". + You can change that by setting this property before saving the SFX. + + + + This property has an effect only when producing a Self-extractor + of flavor SelfExtractorFlavor.WinFormsApplication. + + + + + + + Additional options for the csc.exe compiler, when producing the SFX + EXE. + + + + + + The ZipFile type represents a zip archive file. + + + + + This is the main type in the DotNetZip class library. This class reads and + writes zip files, as defined in the specification + for zip files described by PKWare. The compression for this + implementation is provided by a managed-code version of Zlib, included with + DotNetZip in the classes in the Ionic.Zlib namespace. + + + + This class provides a general purpose zip file capability. Use it to read, + create, or update zip files. When you want to create zip files using a + Stream type to write the zip file, you may want to consider the class. + + + + Both the ZipOutputStream class and the ZipFile class can + be used to create zip files. Both of them support many of the common zip + features, including Unicode, different compression methods and levels, + and ZIP64. They provide very similar performance when creating zip + files. + + + + The ZipFile class is generally easier to use than + ZipOutputStream and should be considered a higher-level interface. For + example, when creating a zip file via calls to the PutNextEntry() and + Write() methods on the ZipOutputStream class, the caller is + responsible for opening the file, reading the bytes from the file, writing + those bytes into the ZipOutputStream, setting the attributes on the + ZipEntry, and setting the created, last modified, and last accessed + timestamps on the zip entry. All of these things are done automatically by a + call to ZipFile.AddFile(). + For this reason, the ZipOutputStream is generally recommended for use + only when your application emits arbitrary data, not necessarily data from a + filesystem file, directly into a zip file, and does so using a Stream + metaphor. + + + + Aside from the differences in programming model, there are other + differences in capability between the two classes. + + + + + ZipFile can be used to read and extract zip files, in addition to + creating zip files. ZipOutputStream cannot read zip files. If you want + to use a stream to read zip files, check out the class. + + + + ZipOutputStream does not support the creation of segmented or spanned + zip files. + + + + ZipOutputStream cannot produce a self-extracting archive. + + + + + Be aware that the ZipFile class implements the interface. In order for ZipFile to + produce a valid zip file, you use use it within a using clause (Using + in VB), or call the Dispose() method explicitly. See the examples + for how to employ a using clause. + + + + + + + Saves the ZipFile instance to a self-extracting zip archive. + + + + + + The generated exe image will execute on any machine that has the .NET + Framework 4.0 installed on it. The generated exe image is also a + valid ZIP file, readable with DotNetZip or another Zip library or tool + such as WinZip. + + + + There are two "flavors" of self-extracting archive. The + WinFormsApplication version will pop up a GUI and allow the + user to select a target directory into which to extract. There's also + a checkbox allowing the user to specify to overwrite existing files, + and another checkbox to allow the user to request that Explorer be + opened to see the extracted files after extraction. The other flavor + is ConsoleApplication. A self-extractor generated with that + flavor setting will run from the command line. It accepts command-line + options to set the overwrite behavior, and to specify the target + extraction directory. + + + + There are a few temporary files created during the saving to a + self-extracting zip. These files are created in the directory pointed + to by , which defaults to . These temporary files are + removed upon successful completion of this method. + + + + When a user runs the WinForms SFX, the user's personal directory (Environment.SpecialFolder.Personal) + will be used as the default extract location. If you want to set the + default extract location, you should use the other overload of + SaveSelfExtractor()/ The user who runs the SFX will have the + opportunity to change the extract directory before extracting. When + the user runs the Command-Line SFX, the user must explicitly specify + the directory to which to extract. The .NET Framework 4.0 is required + on the computer when the self-extracting archive is run. + + + + NB: This method is not available in the "Reduced" DotNetZip library. + + + + + + + string DirectoryPath = "c:\\Documents\\Project7"; + using (ZipFile zip = new ZipFile()) + { + zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)); + zip.Comment = "This will be embedded into a self-extracting console-based exe"; + zip.SaveSelfExtractor("archive.exe", SelfExtractorFlavor.ConsoleApplication); + } + + + Dim DirectoryPath As String = "c:\Documents\Project7" + Using zip As New ZipFile() + zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)) + zip.Comment = "This will be embedded into a self-extracting console-based exe" + zip.SaveSelfExtractor("archive.exe", SelfExtractorFlavor.ConsoleApplication) + End Using + + + + + a pathname, possibly fully qualified, to be created. Typically it + will end in an .exe extension. + + Indicates whether a Winforms or Console self-extractor is + desired. + + + + Saves the ZipFile instance to a self-extracting zip archive, using + the specified save options. + + + + + This method saves a self extracting archive, using the specified save + options. These options include the flavor of the SFX, the default extract + directory, the icon file, and so on. See the documentation + for for more + details. + + + + The user who runs the SFX will have the opportunity to change the extract + directory before extracting. If at the time of extraction, the specified + directory does not exist, the SFX will create the directory before + extracting the files. + + + + + + This example saves a WinForms-based self-extracting archive EXE that + will use c:\ExtractHere as the default extract location. The C# code + shows syntax for .NET 3.0, which uses an object initializer for + the SelfExtractorOptions object. + + string DirectoryPath = "c:\\Documents\\Project7"; + using (ZipFile zip = new ZipFile()) + { + zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)); + zip.Comment = "This will be embedded into a self-extracting WinForms-based exe"; + var options = new SelfExtractorOptions + { + Flavor = SelfExtractorFlavor.WinFormsApplication, + DefaultExtractDirectory = "%USERPROFILE%\\ExtractHere", + PostExtractCommandLine = ExeToRunAfterExtract, + SfxExeWindowTitle = "My Custom Window Title", + RemoveUnpackedFilesAfterExecute = true + }; + zip.SaveSelfExtractor("archive.exe", options); + } + + + Dim DirectoryPath As String = "c:\Documents\Project7" + Using zip As New ZipFile() + zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)) + zip.Comment = "This will be embedded into a self-extracting console-based exe" + Dim options As New SelfExtractorOptions() + options.Flavor = SelfExtractorFlavor.WinFormsApplication + options.DefaultExtractDirectory = "%USERPROFILE%\\ExtractHere" + options.PostExtractCommandLine = ExeToRunAfterExtract + options.SfxExeWindowTitle = "My Custom Window Title" + options.RemoveUnpackedFilesAfterExecute = True + zip.SaveSelfExtractor("archive.exe", options) + End Using + + + + The name of the EXE to generate. + provides the options for creating the + Self-extracting archive. + + + + Adds an item, either a file or a directory, to a zip file archive. + + + + + This method is handy if you are adding things to zip archive and don't + want to bother distinguishing between directories or files. Any files are + added as single entries. A directory added through this method is added + recursively: all files and subdirectories contained within the directory + are added to the ZipFile. + + + + The name of the item may be a relative path or a fully-qualified + path. Remember, the items contained in ZipFile instance get written + to the disk only when you call or a similar + save method. + + + + The directory name used for the file within the archive is the same + as the directory name (potentially a relative path) specified in the + . + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + + + This method has two overloads. + + the name of the file or directory to add. + + The ZipEntry added. + + + + Adds an item, either a file or a directory, to a zip file archive, + explicitly specifying the directory path to be used in the archive. + + + + + If adding a directory, the add is recursive on all files and + subdirectories contained within it. + + + The name of the item may be a relative path or a fully-qualified path. + The item added by this call to the ZipFile is not read from the + disk nor written to the zip file archive until the application calls + Save() on the ZipFile. + + + + This version of the method allows the caller to explicitly specify the + directory path to be used in the archive, which would override the + "natural" path of the filesystem file. + + + + Encryption will be used on the file data if the Password has + been set on the ZipFile object, prior to calling this method. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + Thrown if the file or directory passed in does not exist. + + + the name of the file or directory to add. + + + + The name of the directory path to use within the zip archive. This path + need not refer to an extant directory in the current filesystem. If the + files within the zip are later extracted, this is the path used for the + extracted file. Passing null (Nothing in VB) will use the + path on the fileOrDirectoryName. Passing the empty string ("") will + insert the item at the root path within the archive. + + + + + + + + This example shows how to zip up a set of files into a flat hierarchy, + regardless of where in the filesystem the files originated. The resulting + zip archive will contain a toplevel directory named "flat", which itself + will contain files Readme.txt, MyProposal.docx, and Image1.jpg. A + subdirectory under "flat" called SupportFiles will contain all the files + in the "c:\SupportFiles" directory on disk. + + + String[] itemnames= { + "c:\\fixedContent\\Readme.txt", + "MyProposal.docx", + "c:\\SupportFiles", // a directory + "images\\Image1.jpg" + }; + + try + { + using (ZipFile zip = new ZipFile()) + { + for (int i = 1; i < itemnames.Length; i++) + { + // will add Files or Dirs, recurses and flattens subdirectories + zip.AddItem(itemnames[i],"flat"); + } + zip.Save(ZipToCreate); + } + } + catch (System.Exception ex1) + { + System.Console.Error.WriteLine("exception: {0}", ex1); + } + + + + Dim itemnames As String() = _ + New String() { "c:\fixedContent\Readme.txt", _ + "MyProposal.docx", _ + "SupportFiles", _ + "images\Image1.jpg" } + Try + Using zip As New ZipFile + Dim i As Integer + For i = 1 To itemnames.Length - 1 + ' will add Files or Dirs, recursing and flattening subdirectories. + zip.AddItem(itemnames(i), "flat") + Next i + zip.Save(ZipToCreate) + End Using + Catch ex1 As Exception + Console.Error.WriteLine("exception: {0}", ex1.ToString()) + End Try + + + The ZipEntry added. + + + + Adds a File to a Zip file archive. + + + + + This call collects metadata for the named file in the filesystem, + including the file attributes and the timestamp, and inserts that metadata + into the resulting ZipEntry. Only when the application calls Save() on + the ZipFile, does DotNetZip read the file from the filesystem and + then write the content to the zip file archive. + + + + This method will throw an exception if an entry with the same name already + exists in the ZipFile. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + In this example, three files are added to a Zip archive. The ReadMe.txt + file will be placed in the root of the archive. The .png file will be + placed in a folder within the zip called photos\personal. The pdf file + will be included into a folder within the zip called Desktop. + + + try + { + using (ZipFile zip = new ZipFile()) + { + zip.AddFile("c:\\photos\\personal\\7440-N49th.png"); + zip.AddFile("c:\\Desktop\\2008-Regional-Sales-Report.pdf"); + zip.AddFile("ReadMe.txt"); + + zip.Save("Package.zip"); + } + } + catch (System.Exception ex1) + { + System.Console.Error.WriteLine("exception: " + ex1); + } + + + + Try + Using zip As ZipFile = New ZipFile + zip.AddFile("c:\photos\personal\7440-N49th.png") + zip.AddFile("c:\Desktop\2008-Regional-Sales-Report.pdf") + zip.AddFile("ReadMe.txt") + zip.Save("Package.zip") + End Using + Catch ex1 As Exception + Console.Error.WriteLine("exception: {0}", ex1.ToString) + End Try + + + + This method has two overloads. + + + + + + + The name of the file to add. It should refer to a file in the filesystem. + The name of the file may be a relative path or a fully-qualified path. + + The ZipEntry corresponding to the File added. + + + + Adds a File to a Zip file archive, potentially overriding the path to be + used within the zip archive. + + + + + The file added by this call to the ZipFile is not written to the + zip file archive until the application calls Save() on the ZipFile. + + + + This method will throw an exception if an entry with the same name already + exists in the ZipFile. + + + + This version of the method allows the caller to explicitly specify the + directory path to be used in the archive. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + In this example, three files are added to a Zip archive. The ReadMe.txt + file will be placed in the root of the archive. The .png file will be + placed in a folder within the zip called images. The pdf file will be + included into a folder within the zip called files\docs, and will be + encrypted with the given password. + + + try + { + using (ZipFile zip = new ZipFile()) + { + // the following entry will be inserted at the root in the archive. + zip.AddFile("c:\\datafiles\\ReadMe.txt", ""); + // this image file will be inserted into the "images" directory in the archive. + zip.AddFile("c:\\photos\\personal\\7440-N49th.png", "images"); + // the following will result in a password-protected file called + // files\\docs\\2008-Regional-Sales-Report.pdf in the archive. + zip.Password = "EncryptMe!"; + zip.AddFile("c:\\Desktop\\2008-Regional-Sales-Report.pdf", "files\\docs"); + zip.Save("Archive.zip"); + } + } + catch (System.Exception ex1) + { + System.Console.Error.WriteLine("exception: {0}", ex1); + } + + + + Try + Using zip As ZipFile = New ZipFile + ' the following entry will be inserted at the root in the archive. + zip.AddFile("c:\datafiles\ReadMe.txt", "") + ' this image file will be inserted into the "images" directory in the archive. + zip.AddFile("c:\photos\personal\7440-N49th.png", "images") + ' the following will result in a password-protected file called + ' files\\docs\\2008-Regional-Sales-Report.pdf in the archive. + zip.Password = "EncryptMe!" + zip.AddFile("c:\Desktop\2008-Regional-Sales-Report.pdf", "files\documents") + zip.Save("Archive.zip") + End Using + Catch ex1 As Exception + Console.Error.WriteLine("exception: {0}", ex1) + End Try + + + + + + + + + The name of the file to add. The name of the file may be a relative path + or a fully-qualified path. + + + + Specifies a directory path to use to override any path in the fileName. + This path may, or may not, correspond to a real directory in the current + filesystem. If the files within the zip are later extracted, this is the + path used for the extracted file. Passing null (Nothing in + VB) will use the path on the fileName, if any. Passing the empty string + ("") will insert the item at the root path within the archive. + + + The ZipEntry corresponding to the file added. + + + + This method removes a collection of entries from the ZipFile. + + + + A collection of ZipEntry instances from this zip file to be removed. For + example, you can pass in an array of ZipEntry instances; or you can call + SelectEntries(), and then add or remove entries from that + ICollection<ZipEntry> (ICollection(Of ZipEntry) in VB), and pass + that ICollection to this method. + + + + + + + + This method removes a collection of entries from the ZipFile, by name. + + + + A collection of strings that refer to names of entries to be removed + from the ZipFile. For example, you can pass in an array or a + List of Strings that provide the names of entries to be removed. + + + + + + + + This method adds a set of files to the ZipFile. + + + + + Use this method to add a set of files to the zip archive, in one call. + For example, a list of files received from + System.IO.Directory.GetFiles() can be added to a zip archive in one + call. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to each + ZipEntry added. + + + + + The collection of names of the files to add. Each string should refer to a + file in the filesystem. The name of the file may be a relative path or a + fully-qualified path. + + + + This example shows how to create a zip file, and add a few files into it. + + String ZipFileToCreate = "archive1.zip"; + String DirectoryToZip = "c:\\reports"; + using (ZipFile zip = new ZipFile()) + { + // Store all files found in the top level directory, into the zip archive. + String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip); + zip.AddFiles(filenames); + zip.Save(ZipFileToCreate); + } + + + + Dim ZipFileToCreate As String = "archive1.zip" + Dim DirectoryToZip As String = "c:\reports" + Using zip As ZipFile = New ZipFile + ' Store all files found in the top level directory, into the zip archive. + Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip) + zip.AddFiles(filenames) + zip.Save(ZipFileToCreate) + End Using + + + + + + + + Adds or updates a set of files in the ZipFile. + + + + + Any files that already exist in the archive are updated. Any files that + don't yet exist in the archive are added. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to each + ZipEntry added. + + + + + The collection of names of the files to update. Each string should refer to a file in + the filesystem. The name of the file may be a relative path or a fully-qualified path. + + + + + + Adds a set of files to the ZipFile, using the + specified directory path in the archive. + + + + + Any directory structure that may be present in the + filenames contained in the list is "flattened" in the + archive. Each file in the list is added to the archive in + the specified top-level directory. + + + + For ZipFile properties including , , , , , , and , their respective values at the + time of this call will be applied to each ZipEntry added. + + + + + The names of the files to add. Each string should refer to + a file in the filesystem. The name of the file may be a + relative path or a fully-qualified path. + + + + Specifies a directory path to use to override any path in the file name. + Th is path may, or may not, correspond to a real directory in the current + filesystem. If the files within the zip are later extracted, this is the + path used for the extracted file. Passing null (Nothing in + VB) will use the path on each of the fileNames, if any. Passing + the empty string ("") will insert the item at the root path within the + archive. + + + + + + + Adds a set of files to the ZipFile, using the specified directory + path in the archive, and preserving the full directory structure in the + filenames. + + + + + + Think of the as a "root" or + base directory used in the archive for the files that get added. when + is true, the hierarchy of files + found in the filesystem will be placed, with the hierarchy intact, + starting at that root in the archive. When preserveDirHierarchy + is false, the path hierarchy of files is flattned, and the flattened + set of files gets placed in the root within the archive as specified in + directoryPathInArchive. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to each + ZipEntry added. + + + + + + The names of the files to add. Each string should refer to a file in the + filesystem. The name of the file may be a relative path or a + fully-qualified path. + + + + Specifies a directory path to use as a prefix for each entry name. + This path may, or may not, correspond to a real directory in the current + filesystem. If the files within the zip are later extracted, this is the + path used for the extracted file. Passing null (Nothing in + VB) will use the path on each of the fileNames, if any. Passing + the empty string ("") will insert the item at the root path within the + archive. + + + + whether the entries in the zip archive will reflect the directory + hierarchy that is present in the various filenames. For example, if + includes two paths, + \Animalia\Chordata\Mammalia\Info.txt and + \Plantae\Magnoliophyta\Dicotyledon\Info.txt, then calling this method + with = false will + result in an exception because of a duplicate entry name, while + calling this method with = + true will result in the full direcory paths being included in + the entries added to the ZipFile. + + + + + + Adds or updates a set of files to the ZipFile, using the specified + directory path in the archive. + + + + + + Any files that already exist in the archive are updated. Any files that + don't yet exist in the archive are added. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to each + ZipEntry added. + + + + + The names of the files to add or update. Each string should refer to a + file in the filesystem. The name of the file may be a relative path or a + fully-qualified path. + + + + Specifies a directory path to use to override any path in the file name. + This path may, or may not, correspond to a real directory in the current + filesystem. If the files within the zip are later extracted, this is the + path used for the extracted file. Passing null (Nothing in + VB) will use the path on each of the fileNames, if any. Passing + the empty string ("") will insert the item at the root path within the + archive. + + + + + + + Adds or Updates a File in a Zip file archive. + + + + + This method adds a file to a zip archive, or, if the file already exists + in the zip archive, this method Updates the content of that given filename + in the zip archive. The UpdateFile method might more accurately be + called "AddOrUpdateFile". + + + + Upon success, there is no way for the application to learn whether the file + was added versus updated. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + This example shows how to Update an existing entry in a zipfile. The first + call to UpdateFile adds the file to the newly-created zip archive. The + second call to UpdateFile updates the content for that file in the zip + archive. + + + using (ZipFile zip1 = new ZipFile()) + { + // UpdateFile might more accurately be called "AddOrUpdateFile" + zip1.UpdateFile("MyDocuments\\Readme.txt"); + zip1.UpdateFile("CustomerList.csv"); + zip1.Comment = "This zip archive has been created."; + zip1.Save("Content.zip"); + } + + using (ZipFile zip2 = ZipFile.Read("Content.zip")) + { + zip2.UpdateFile("Updates\\Readme.txt"); + zip2.Comment = "This zip archive has been updated: The Readme.txt file has been changed."; + zip2.Save(); + } + + + + Using zip1 As New ZipFile + ' UpdateFile might more accurately be called "AddOrUpdateFile" + zip1.UpdateFile("MyDocuments\Readme.txt") + zip1.UpdateFile("CustomerList.csv") + zip1.Comment = "This zip archive has been created." + zip1.Save("Content.zip") + End Using + + Using zip2 As ZipFile = ZipFile.Read("Content.zip") + zip2.UpdateFile("Updates\Readme.txt") + zip2.Comment = "This zip archive has been updated: The Readme.txt file has been changed." + zip2.Save + End Using + + + + + + + + + The name of the file to add or update. It should refer to a file in the + filesystem. The name of the file may be a relative path or a + fully-qualified path. + + + + The ZipEntry corresponding to the File that was added or updated. + + + + + Adds or Updates a File in a Zip file archive. + + + + + This method adds a file to a zip archive, or, if the file already exists + in the zip archive, this method Updates the content of that given filename + in the zip archive. + + + + This version of the method allows the caller to explicitly specify the + directory path to be used in the archive. The entry to be added or + updated is found by using the specified directory path, combined with the + basename of the specified filename. + + + + Upon success, there is no way for the application to learn if the file was + added versus updated. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + + + The name of the file to add or update. It should refer to a file in the + filesystem. The name of the file may be a relative path or a + fully-qualified path. + + + + Specifies a directory path to use to override any path in the + fileName. This path may, or may not, correspond to a real + directory in the current filesystem. If the files within the zip are + later extracted, this is the path used for the extracted file. Passing + null (Nothing in VB) will use the path on the + fileName, if any. Passing the empty string ("") will insert the + item at the root path within the archive. + + + + The ZipEntry corresponding to the File that was added or updated. + + + + + Add or update a directory in a zip archive. + + + + If the specified directory does not exist in the archive, then this method + is equivalent to calling AddDirectory(). If the specified + directory already exists in the archive, then this method updates any + existing entries, and adds any new entries. Any entries that are in the + zip archive but not in the specified directory, are left alone. In other + words, the contents of the zip file will be a union of the previous + contents and the new files. + + + + + + + + The path to the directory to be added to the zip archive, or updated in + the zip archive. + + + + The ZipEntry corresponding to the Directory that was added or updated. + + + + + Add or update a directory in the zip archive at the specified root + directory in the archive. + + + + If the specified directory does not exist in the archive, then this method + is equivalent to calling AddDirectory(). If the specified + directory already exists in the archive, then this method updates any + existing entries, and adds any new entries. Any entries that are in the + zip archive but not in the specified directory, are left alone. In other + words, the contents of the zip file will be a union of the previous + contents and the new files. + + + + + + + + The path to the directory to be added to the zip archive, or updated + in the zip archive. + + + + Specifies a directory path to use to override any path in the + directoryName. This path may, or may not, correspond to a real + directory in the current filesystem. If the files within the zip are + later extracted, this is the path used for the extracted file. Passing + null (Nothing in VB) will use the path on the + directoryName, if any. Passing the empty string ("") will insert + the item at the root path within the archive. + + + + The ZipEntry corresponding to the Directory that was added or updated. + + + + + Add or update a file or directory in the zip archive. + + + + + This is useful when the application is not sure or does not care if the + item to be added is a file or directory, and does not know or does not + care if the item already exists in the ZipFile. Calling this method + is equivalent to calling RemoveEntry() if an entry by the same name + already exists, followed calling by AddItem(). + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + + + the path to the file or directory to be added or updated. + + + + + Add or update a file or directory. + + + + + This method is useful when the application is not sure or does not care if + the item to be added is a file or directory, and does not know or does not + care if the item already exists in the ZipFile. Calling this method + is equivalent to calling RemoveEntry(), if an entry by that name + exists, and then calling AddItem(). + + + + This version of the method allows the caller to explicitly specify the + directory path to be used for the item being added to the archive. The + entry or entries that are added or updated will use the specified + DirectoryPathInArchive. Extracting the entry from the archive will + result in a file stored in that directory path. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + + + The path for the File or Directory to be added or updated. + + + Specifies a directory path to use to override any path in the + itemName. This path may, or may not, correspond to a real + directory in the current filesystem. If the files within the zip are + later extracted, this is the path used for the extracted file. Passing + null (Nothing in VB) will use the path on the + itemName, if any. Passing the empty string ("") will insert the + item at the root path within the archive. + + + + + Adds a named entry into the zip archive, taking content for the entry + from a string. + + + + Calling this method creates an entry using the given fileName and + directory path within the archive. There is no need for a file by the + given name to exist in the filesystem; the name is used within the zip + archive only. The content for the entry is encoded using the default text + encoding for the machine. + + + + The content of the file, should it be extracted from the zip. + + + + The name, including any path, to use for the entry within the archive. + + + The ZipEntry added. + + + + This example shows how to add an entry to the zipfile, using a string as + content for that entry. + + + string Content = "This string will be the content of the Readme.txt file in the zip archive."; + using (ZipFile zip1 = new ZipFile()) + { + zip1.AddFile("MyDocuments\\Resume.doc", "files"); + zip1.AddEntry("Readme.txt", Content); + zip1.Comment = "This zip file was created at " + System.DateTime.Now.ToString("G"); + zip1.Save("Content.zip"); + } + + + + Public Sub Run() + Dim Content As String = "This string will be the content of the Readme.txt file in the zip archive." + Using zip1 As ZipFile = New ZipFile + zip1.AddEntry("Readme.txt", Content) + zip1.AddFile("MyDocuments\Resume.doc", "files") + zip1.Comment = ("This zip file was created at " & DateTime.Now.ToString("G")) + zip1.Save("Content.zip") + End Using + End Sub + + + + + + Adds a named entry into the zip archive, taking content for the entry + from a string, and using the specified text encoding. + + + + + + Calling this method creates an entry using the given fileName and + directory path within the archive. There is no need for a file by the + given name to exist in the filesystem; the name is used within the zip + archive only. + + + + The content for the entry, a string value, is encoded using the given + text encoding. A BOM (byte-order-mark) is emitted into the file, if the + Encoding parameter is set for that. + + + + Most Encoding classes support a constructor that accepts a boolean, + indicating whether to emit a BOM or not. For example see . + + + + + + The name, including any path, to use within the archive for the entry. + + + + The content of the file, should it be extracted from the zip. + + + + The text encoding to use when encoding the string. Be aware: This is + distinct from the text encoding used to encode the fileName, as specified + in . + + + The ZipEntry added. + + + + + Create an entry in the ZipFile using the given Stream + as input. The entry will have the given filename. + + + + + + The application should provide an open, readable stream; in this case it + will be read during the call to or one of + its overloads. + + + + The passed stream will be read from its current position. If + necessary, callers should set the position in the stream before + calling AddEntry(). This might be appropriate when using this method + with a MemoryStream, for example. + + + + In cases where a large number of streams will be added to the + ZipFile, the application may wish to avoid maintaining all of the + streams open simultaneously. To handle this situation, the application + should use the + overload. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + This example adds a single entry to a ZipFile via a Stream. + + + + String zipToCreate = "Content.zip"; + String fileNameInArchive = "Content-From-Stream.bin"; + using (System.IO.Stream streamToRead = MyStreamOpener()) + { + using (ZipFile zip = new ZipFile()) + { + ZipEntry entry= zip.AddEntry(fileNameInArchive, streamToRead); + zip.AddFile("Readme.txt"); + zip.Save(zipToCreate); // the stream is read implicitly here + } + } + + + + Dim zipToCreate As String = "Content.zip" + Dim fileNameInArchive As String = "Content-From-Stream.bin" + Using streamToRead as System.IO.Stream = MyStreamOpener() + Using zip As ZipFile = New ZipFile() + Dim entry as ZipEntry = zip.AddEntry(fileNameInArchive, streamToRead) + zip.AddFile("Readme.txt") + zip.Save(zipToCreate) '' the stream is read implicitly, here + End Using + End Using + + + + + + + The name, including any path, which is shown in the zip file for the added + entry. + + + The input stream from which to grab content for the file + + The ZipEntry added. + + + + Add a ZipEntry for which content is written directly by the application. + + + + + When the application needs to write the zip entry data, use this + method to add the ZipEntry. For example, in the case that the + application wishes to write the XML representation of a DataSet into + a ZipEntry, the application can use this method to do so. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + About progress events: When using the WriteDelegate, DotNetZip does + not issue any SaveProgress events with EventType = + Saving_EntryBytesRead. (This is because it is the + application's code that runs in WriteDelegate - there's no way for + DotNetZip to know when to issue a EntryBytesRead event.) + Applications that want to update a progress bar or similar status + indicator should do so from within the WriteDelegate + itself. DotNetZip will issue the other SaveProgress events, + including + Saving_Started, + + Saving_BeforeWriteEntry, and + Saving_AfterWriteEntry. + + + + Note: When you use PKZip encryption, it's normally necessary to + compute the CRC of the content to be encrypted, before compressing or + encrypting it. Therefore, when using PKZip encryption with a + WriteDelegate, the WriteDelegate CAN BE called twice: once to compute + the CRC, and the second time to potentially compress and + encrypt. Surprising, but true. This is because PKWARE specified that + the encryption initialization data depends on the CRC. + If this happens, for each call of the delegate, your + application must stream the same entry data in its entirety. If your + application writes different data during the second call, it will + result in a corrupt zip file. + + + + The double-read behavior happens with all types of entries, not only + those that use WriteDelegate. It happens if you add an entry from a + filesystem file, or using a string, or a stream, or an opener/closer + pair. But in those cases, DotNetZip takes care of reading twice; in + the case of the WriteDelegate, the application code gets invoked + twice. Be aware. + + + + As you can imagine, this can cause performance problems for large + streams, and it can lead to correctness problems when you use a + WriteDelegate. This is a pretty big pitfall. There are two + ways to avoid it. First, and most preferred: don't use PKZIP + encryption. If you use the WinZip AES encryption, this problem + doesn't occur, because the encryption protocol doesn't require the CRC + up front. Second: if you do choose to use PKZIP encryption, write out + to a non-seekable stream (like standard output, or the + Response.OutputStream in an ASP.NET application). In this case, + DotNetZip will use an alternative encryption protocol that does not + rely on the CRC of the content. This also implies setting bit 3 in + the zip entry, which still presents problems for some zip tools. + + + + In the future I may modify DotNetZip to *always* use bit 3 when PKZIP + encryption is in use. This seems like a win overall, but there will + be some work involved. If you feel strongly about it, visit the + DotNetZip forums and vote up the Workitem + tracking this issue. + + + + + the name of the entry to add + the delegate which will write the entry content + the ZipEntry added + + + + This example shows an application filling a DataSet, then saving the + contents of that DataSet as XML, into a ZipEntry in a ZipFile, using an + anonymous delegate in C#. The DataSet XML is never saved to a disk file. + + + var c1= new System.Data.SqlClient.SqlConnection(connstring1); + var da = new System.Data.SqlClient.SqlDataAdapter() + { + SelectCommand= new System.Data.SqlClient.SqlCommand(strSelect, c1) + }; + + DataSet ds1 = new DataSet(); + da.Fill(ds1, "Invoices"); + + using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile()) + { + zip.AddEntry(zipEntryName, (name,stream) => ds1.WriteXml(stream) ); + zip.Save(zipFileName); + } + + + + + + This example uses an anonymous method in C# as the WriteDelegate to provide + the data for the ZipEntry. The example is a bit contrived - the + AddFile() method is a simpler way to insert the contents of a file + into an entry in a zip file. On the other hand, if there is some sort of + processing or transformation of the file contents required before writing, + the application could use the WriteDelegate to do it, in this way. + + + using (var input = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite )) + { + using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile()) + { + zip.AddEntry(zipEntryName, (name,output) => + { + byte[] buffer = new byte[BufferSize]; + int n; + while ((n = input.Read(buffer, 0, buffer.Length)) != 0) + { + // could transform the data here... + output.Write(buffer, 0, n); + // could update a progress bar here + } + }); + + zip.Save(zipFileName); + } + } + + + + + + This example uses a named delegate in VB to write data for the given + ZipEntry (VB9 does not have anonymous delegates). The example here is a bit + contrived - a simpler way to add the contents of a file to a ZipEntry is to + simply use the appropriate AddFile() method. The key scenario for + which the WriteDelegate makes sense is saving a DataSet, in XML + format, to the zip file. The DataSet can write XML to a stream, and the + WriteDelegate is the perfect place to write into the zip file. There may be + other data structures that can write to a stream, but cannot be read as a + stream. The WriteDelegate would be appropriate for those cases as + well. + + + Private Sub WriteEntry (ByVal name As String, ByVal output As Stream) + Using input As FileStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) + Dim n As Integer = -1 + Dim buffer As Byte() = New Byte(BufferSize){} + Do While n <> 0 + n = input.Read(buffer, 0, buffer.Length) + output.Write(buffer, 0, n) + Loop + End Using + End Sub + + Public Sub Run() + Using zip = New ZipFile + zip.AddEntry(zipEntryName, New WriteDelegate(AddressOf WriteEntry)) + zip.Save(zipFileName) + End Using + End Sub + + + + + + Add an entry, for which the application will provide a stream + containing the entry data, on a just-in-time basis. + + + + + In cases where the application wishes to open the stream that + holds the content for the ZipEntry, on a just-in-time basis, the + application can use this method. The application provides an + opener delegate that will be called by the DotNetZip library to + obtain a readable stream that can be read to get the bytes for + the given entry. Typically, this delegate opens a stream. + Optionally, the application can provide a closer delegate as + well, which will be called by DotNetZip when all bytes have been + read from the entry. + + + + These delegates are called from within the scope of the call to + ZipFile.Save(). + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + This example uses anonymous methods in C# to open and close the + source stream for the content for a zip entry. + + + using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile()) + { + zip.AddEntry(zipEntryName, + (name) => File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ), + (name, stream) => stream.Close() + ); + + zip.Save(zipFileName); + } + + + + + + + This example uses delegates in VB.NET to open and close the + the source stream for the content for a zip entry. VB 9.0 lacks + support for "Sub" lambda expressions, and so the CloseDelegate must + be an actual, named Sub. + + + + Function MyStreamOpener(ByVal entryName As String) As Stream + '' This simply opens a file. You probably want to do somethinig + '' more involved here: open a stream to read from a database, + '' open a stream on an HTTP connection, and so on. + Return File.OpenRead(entryName) + End Function + + Sub MyStreamCloser(entryName As String, stream As Stream) + stream.Close() + End Sub + + Public Sub Run() + Dim dirToZip As String = "fodder" + Dim zipFileToCreate As String = "Archive.zip" + Dim opener As OpenDelegate = AddressOf MyStreamOpener + Dim closer As CloseDelegate = AddressOf MyStreamCloser + Dim numFilestoAdd As Int32 = 4 + Using zip As ZipFile = New ZipFile + Dim i As Integer + For i = 0 To numFilesToAdd - 1 + zip.AddEntry(String.Format("content-{0:000}.txt"), opener, closer) + Next i + zip.Save(zipFileToCreate) + End Using + End Sub + + + + + the name of the entry to add + + the delegate that will be invoked by ZipFile.Save() to get the + readable stream for the given entry. ZipFile.Save() will call + read on this stream to obtain the data for the entry. This data + will then be compressed and written to the newly created zip + file. + + + the delegate that will be invoked to close the stream. This may + be null (Nothing in VB), in which case no call is makde to close + the stream. + + the ZipEntry added + + + + + Updates the given entry in the ZipFile, using the given + string as content for the ZipEntry. + + + + + + Calling this method is equivalent to removing the ZipEntry for + the given file name and directory path, if it exists, and then calling + . See the documentation for + that method for further explanation. The string content is encoded + using the default encoding for the machine. This encoding is distinct + from the encoding used for the filename itself. See + . + + + + + + The name, including any path, to use within the archive for the entry. + + + + The content of the file, should it be extracted from the zip. + + + The ZipEntry added. + + + + + Updates the given entry in the ZipFile, using the given string as + content for the ZipEntry. + + + + Calling this method is equivalent to removing the ZipEntry for the + given file name and directory path, if it exists, and then calling . See the + documentation for that method for further explanation. + + + + The name, including any path, to use within the archive for the entry. + + + + The content of the file, should it be extracted from the zip. + + + + The text encoding to use when encoding the string. Be aware: This is + distinct from the text encoding used to encode the filename. See . + + + The ZipEntry added. + + + + + Updates the given entry in the ZipFile, using the given delegate + as the source for content for the ZipEntry. + + + + Calling this method is equivalent to removing the ZipEntry for the + given file name and directory path, if it exists, and then calling . See the + documentation for that method for further explanation. + + + + The name, including any path, to use within the archive for the entry. + + + the delegate which will write the entry content. + + The ZipEntry added. + + + + + Updates the given entry in the ZipFile, using the given delegates + to open and close the stream that provides the content for the ZipEntry. + + + + Calling this method is equivalent to removing the ZipEntry for the + given file name and directory path, if it exists, and then calling . See the + documentation for that method for further explanation. + + + + The name, including any path, to use within the archive for the entry. + + + + the delegate that will be invoked to open the stream + + + the delegate that will be invoked to close the stream + + + The ZipEntry added or updated. + + + + + Updates the given entry in the ZipFile, using the given stream as + input, and the given filename and given directory Path. + + + + + Calling the method is equivalent to calling RemoveEntry() if an + entry by the same name already exists, and then calling AddEntry() + with the given fileName and stream. + + + + The stream must be open and readable during the call to + ZipFile.Save. You can dispense the stream on a just-in-time basis + using the property. Check the + documentation of that property for more information. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + + + The name, including any path, to use within the archive for the entry. + + + The input stream from which to read file data. + The ZipEntry added. + + + + Add an entry into the zip archive using the given filename and + directory path within the archive, and the given content for the + file. No file is created in the filesystem. + + + The data to use for the entry. + + + The name, including any path, to use within the archive for the entry. + + + The ZipEntry added. + + + + Updates the given entry in the ZipFile, using the given byte + array as content for the entry. + + + + Calling this method is equivalent to removing the ZipEntry + for the given filename and directory path, if it exists, and then + calling . See the + documentation for that method for further explanation. + + + + The name, including any path, to use within the archive for the entry. + + + The content to use for the ZipEntry. + + The ZipEntry added. + + + + + Adds the contents of a filesystem directory to a Zip file archive. + + + + + + The name of the directory may be a relative path or a fully-qualified + path. Any files within the named directory are added to the archive. Any + subdirectories within the named directory are also added to the archive, + recursively. + + + + Top-level entries in the named directory will appear as top-level entries + in the zip archive. Entries in subdirectories in the named directory will + result in entries in subdirectories in the zip archive. + + + + If you want the entries to appear in a containing directory in the zip + archive itself, then you should call the AddDirectory() overload that + allows you to explicitly specify a directory path for use in the archive. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to each + ZipEntry added. + + + + + + + + + + This method has 2 overloads. + + The name of the directory to add. + The ZipEntry added. + + + + Adds the contents of a filesystem directory to a Zip file archive, + overriding the path to be used for entries in the archive. + + + + + The name of the directory may be a relative path or a fully-qualified + path. The add operation is recursive, so that any files or subdirectories + within the name directory are also added to the archive. + + + + Top-level entries in the named directory will appear as top-level entries + in the zip archive. Entries in subdirectories in the named directory will + result in entries in subdirectories in the zip archive. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to each + ZipEntry added. + + + + + + + In this code, calling the ZipUp() method with a value of "c:\reports" for + the directory parameter will result in a zip file structure in which all + entries are contained in a toplevel "reports" directory. + + + + public void ZipUp(string targetZip, string directory) + { + using (var zip = new ZipFile()) + { + zip.AddDirectory(directory, System.IO.Path.GetFileName(directory)); + zip.Save(targetZip); + } + } + + + + + + + + The name of the directory to add. + + + Specifies a directory path to use to override any path in the + DirectoryName. This path may, or may not, correspond to a real directory + in the current filesystem. If the zip is later extracted, this is the + path used for the extracted file or directory. Passing null + (Nothing in VB) or the empty string ("") will insert the items at + the root path within the archive. + + + The ZipEntry added. + + + + Creates a directory in the zip archive. + + + + + + Use this when you want to create a directory in the archive but there is + no corresponding filesystem representation for that directory. + + + + You will probably not need to do this in your code. One of the only times + you will want to do this is if you want an empty directory in the zip + archive. The reason: if you add a file to a zip archive that is stored + within a multi-level directory, all of the directory tree is implicitly + created in the zip archive. + + + + + + The name of the directory to create in the archive. + + The ZipEntry added. + + + + Checks a zip file to see if its directory is consistent. + + + + + + In cases of data error, the directory within a zip file can get out + of synch with the entries in the zip file. This method checks the + given zip file and returns true if this has occurred. + + + This method may take a long time to run for large zip files. + + + This method is not supported in the Reduced version of DotNetZip. + + + + Developers using COM can use the ComHelper.CheckZip(String) + method. + + + + + The filename to of the zip file to check. + + true if the named zip file checks OK. Otherwise, false. + + + + + + + Checks a zip file to see if its directory is consistent, + and optionally fixes the directory if necessary. + + + + + + In cases of data error, the directory within a zip file can get out of + synch with the entries in the zip file. This method checks the given + zip file, and returns true if this has occurred. It also optionally + fixes the zipfile, saving the fixed copy in Name_Fixed.zip. + + + + This method may take a long time to run for large zip files. It + will take even longer if the file actually needs to be fixed, and if + fixIfNecessary is true. + + + + This method is not supported in the Reduced version of DotNetZip. + + + + + The filename to of the zip file to check. + + If true, the method will fix the zip file if + necessary. + + + a TextWriter in which messages generated while checking will be written. + + + true if the named zip is OK; false if the file needs to be fixed. + + + + + + + Rewrite the directory within a zipfile. + + + + + + In cases of data error, the directory in a zip file can get out of + synch with the entries in the zip file. This method attempts to fix + the zip file if this has occurred. + + + This can take a long time for large zip files. + + This won't work if the zip file uses a non-standard + code page - neither IBM437 nor UTF-8. + + + This method is not supported in the Reduced or Compact Framework + versions of DotNetZip. + + + + Developers using COM can use the ComHelper.FixZipDirectory(String) + method. + + + + + The filename to of the zip file to fix. + + + + + + + Verify the password on a zip file. + + + + + Keep in mind that passwords in zipfiles are applied to + zip entries, not to the entire zip file. So testing a + zipfile for a particular password doesn't work in the + general case. On the other hand, it's often the case + that a single password will be used on all entries in a + zip file. This method works for that case. + + + There is no way to check a password without doing the + decryption. So this code decrypts and extracts the given + zipfile into + + + + The filename to of the zip file to fix. + + The password to check. + + a bool indicating whether the password matches. + + + + Provides a human-readable string with information about the ZipFile. + + + + + The information string contains 10 lines or so, about each ZipEntry, + describing whether encryption is in use, the compressed and uncompressed + length of the entry, the offset of the entry, and so on. As a result the + information string can be very long for zip files that contain many + entries. + + + This information is mostly useful for diagnostic purposes. + + + + + + Indicates whether to perform a full scan of the zip file when reading it. + + + + + + You almost never want to use this property. + + + + When reading a zip file, if this flag is true (True in + VB), the entire zip archive will be scanned and searched for entries. + For large archives, this can take a very, long time. The much more + efficient default behavior is to read the zip directory, which is + stored at the end of the zip file. But, in some cases the directory is + corrupted and you need to perform a full scan of the zip file to + determine the contents of the zip file. This property lets you do + that, when necessary. + + + + This flag is effective only when calling . Normally you would read a ZipFile with the + static ZipFile.Read + method. But you can't set the FullScan property on the + ZipFile instance when you use a static factory method like + ZipFile.Read. + + + + + + + This example shows how to read a zip file using the full scan approach, + and then save it, thereby producing a corrected zip file. + + + using (var zip = new ZipFile()) + { + zip.FullScan = true; + zip.Initialize(zipFileName); + zip.Save(newName); + } + + + + Using zip As New ZipFile + zip.FullScan = True + zip.Initialize(zipFileName) + zip.Save(newName) + End Using + + + + + + + Whether to sort the ZipEntries before saving the file. + + + + The default is false. If you have a large number of zip entries, the sort + alone can consume significant time. + + + + + using (var zip = new ZipFile()) + { + zip.AddFiles(filesToAdd); + zip.SortEntriesBeforeSaving = true; + zip.Save(name); + } + + + + Using zip As New ZipFile + zip.AddFiles(filesToAdd) + zip.SortEntriesBeforeSaving = True + zip.Save(name) + End Using + + + + + + + Indicates whether NTFS Reparse Points, like junctions, should be + traversed during calls to AddDirectory(). + + + + By default, calls to AddDirectory() will traverse NTFS reparse + points, like mounted volumes, and directory junctions. An example + of a junction is the "My Music" directory in Windows Vista. In some + cases you may not want DotNetZip to traverse those directories. In + that case, set this property to false. + + + + + using (var zip = new ZipFile()) + { + zip.AddDirectoryWillTraverseReparsePoints = false; + zip.AddDirectory(dirToZip,"fodder"); + zip.Save(zipFileToCreate); + } + + + + + + Size of the IO buffer used while saving. + + + + + + First, let me say that you really don't need to bother with this. It is + here to allow for optimizations that you probably won't make! It will work + fine if you don't set or get this property at all. Ok? + + + + Now that we have that out of the way, the fine print: This + property affects the size of the buffer that is used for I/O for each + entry contained in the zip file. When a file is read in to be compressed, + it uses a buffer given by the size here. When you update a zip file, the + data for unmodified entries is copied from the first zip file to the + other, through a buffer given by the size here. + + + + Changing the buffer size affects a few things: first, for larger buffer + sizes, the memory used by the ZipFile, obviously, will be larger + during I/O operations. This may make operations faster for very much + larger files. Last, for any given entry, when you use a larger buffer + there will be fewer progress events during I/O operations, because there's + one progress event generated for each time the buffer is filled and then + emptied. + + + + The default buffer size is 8k. Increasing the buffer size may speed + things up as you compress larger files. But there are no hard-and-fast + rules here, eh? You won't know til you test it. And there will be a + limit where ever larger buffers actually slow things down. So as I said + in the beginning, it's probably best if you don't set or get this property + at all. + + + + + + This example shows how you might set a large buffer size for efficiency when + dealing with zip entries that are larger than 1gb. + + using (ZipFile zip = new ZipFile()) + { + zip.SaveProgress += this.zip1_SaveProgress; + zip.AddDirectory(directoryToZip, ""); + zip.UseZip64WhenSaving = Zip64Option.Always; + zip.BufferSize = 65536*8; // 65536 * 8 = 512k + zip.Save(ZipFileToCreate); + } + + + + + + Size of the work buffer to use for the ZLIB codec during compression. + + + + + When doing ZLIB or Deflate compression, the library fills a buffer, + then passes it to the compressor for compression. Then the library + reads out the compressed bytes. This happens repeatedly until there + is no more uncompressed data to compress. This property sets the + size of the buffer that will be used for chunk-wise compression. In + order for the setting to take effect, your application needs to set + this property before calling one of the ZipFile.Save() + overloads. + + + Setting this affects the performance and memory efficiency of + compression and decompression. For larger files, setting this to a + larger size may improve compression performance, but the exact + numbers vary depending on available memory, the size of the streams + you are compressing, and a bunch of other variables. I don't have + good firm recommendations on how to set it. You'll have to test it + yourself. Or just leave it alone and accept the default. + + + + + + Indicates whether extracted files should keep their paths as + stored in the zip archive. + + + + + This property affects Extraction. It is not used when creating zip + archives. + + + + With this property set to false, the default, extracting entries + from a zip file will create files in the filesystem that have the full + path associated to the entry within the zip file. With this property set + to true, extracting entries from the zip file results in files + with no path: the folders are "flattened." + + + + An example: suppose the zip file contains entries /directory1/file1.txt and + /directory2/file2.txt. With FlattenFoldersOnExtract set to false, + the files created will be \directory1\file1.txt and \directory2\file2.txt. + With the property set to true, the files created are file1.txt and file2.txt. + + + + + + + The compression strategy to use for all entries. + + + + Set the Strategy used by the ZLIB-compatible compressor, when + compressing entries using the DEFLATE method. Different compression + strategies work better on different sorts of data. The strategy + parameter can affect the compression ratio and the speed of + compression but not the correctness of the compresssion. For more + information see Ionic.Zlib.CompressionStrategy. + + + + + The name of the ZipFile, on disk. + + + + + + When the ZipFile instance was created by reading an archive using + one of the ZipFile.Read methods, this property represents the name + of the zip file that was read. When the ZipFile instance was + created by using the no-argument constructor, this value is null + (Nothing in VB). + + + + If you use the no-argument constructor, and you then explicitly set this + property, when you call , this name will + specify the name of the zip file created. Doing so is equivalent to + calling . When instantiating a + ZipFile by reading from a stream or byte array, the Name + property remains null. When saving to a stream, the Name + property is implicitly set to null. + + + + + + Sets the compression level to be used for entries subsequently added to + the zip archive. + + + + + Varying the compression level used on entries can affect the + size-vs-speed tradeoff when compression and decompressing data streams + or files. + + + + As with some other properties on the ZipFile class, like , , and , setting this property on a ZipFile + instance will cause the specified CompressionLevel to be used on all + items that are subsequently added to the + ZipFile instance. If you set this property after you have added + items to the ZipFile, but before you have called Save(), + those items will not use the specified compression level. + + + + If you do not set this property, the default compression level is used, + which normally gives a good balance of compression efficiency and + compression speed. In some tests, using BestCompression can + double the time it takes to compress, while delivering just a small + increase in compression efficiency. This behavior will vary with the + type of data you compress. If you are in doubt, just leave this setting + alone, and accept the default. + + + + + + The compression method for the zipfile. + + + + By default, the compression method is CompressionMethod.Deflate. + + + + + + + A comment attached to the zip archive. + + + + + + This property is read/write. It allows the application to specify a + comment for the ZipFile, or read the comment for the + ZipFile. After setting this property, changes are only made + permanent when you call a Save() method. + + + + According to PKWARE's + zip specification, the comment is not encrypted, even if there is a + password set on the zip file. + + + + The specification does not describe how to indicate the encoding used + on a comment string. Many "compliant" zip tools and libraries use + IBM437 as the code page for comments; DotNetZip, too, follows that + practice. On the other hand, there are situations where you want a + Comment to be encoded with something else, for example using code page + 950 "Big-5 Chinese". To fill that need, DotNetZip will encode the + comment following the same procedure it follows for encoding + filenames: (a) if is + Never, it uses the default encoding (IBM437). (b) if is Always, it always uses the + alternate encoding (). (c) if is AsNecessary, it uses the + alternate encoding only if the default encoding is not sufficient for + encoding the comment - in other words if decoding the result does not + produce the original string. This decision is taken at the time of + the call to ZipFile.Save(). + + + + When creating a zip archive using this library, it is possible to change + the value of between each + entry you add, and between adding entries and the call to + Save(). Don't do this. It will likely result in a zip file that is + not readable by any tool or application. For best interoperability, leave + alone, or specify it only + once, before adding any entries to the ZipFile instance. + + + + + + + Specifies whether the Creation, Access, and Modified times for entries + added to the zip file will be emitted in “Windows format” + when the zip archive is saved. + + + + + An application creating a zip archive can use this flag to explicitly + specify that the file times for the entries should or should not be stored + in the zip archive in the format used by Windows. By default this flag is + true, meaning the Windows-format times are stored in the zip + archive. + + + + When adding an entry from a file or directory, the Creation (), Access (), and Modified () times for the given entry are + automatically set from the filesystem values. When adding an entry from a + stream or string, all three values are implicitly set to + DateTime.Now. Applications can also explicitly set those times by + calling . + + + + PKWARE's + zip specification describes multiple ways to format these times in a + zip file. One is the format Windows applications normally use: 100ns ticks + since January 1, 1601 UTC. The other is a format Unix applications typically + use: seconds since January 1, 1970 UTC. Each format can be stored in an + "extra field" in the zip entry when saving the zip archive. The former + uses an extra field with a Header Id of 0x000A, while the latter uses a + header ID of 0x5455, although you probably don't need to know that. + + + + Not all tools and libraries can interpret these fields. Windows + compressed folders is one that can read the Windows Format timestamps, + while I believe the Infozip + tools can read the Unix format timestamps. Some tools and libraries + may be able to read only one or the other. DotNetZip can read or write + times in either or both formats. + + + + The times stored are taken from , , and . + + + + The value set here applies to all entries subsequently added to the + ZipFile. + + + + This property is not mutually exclusive of the property. It is possible and + legal and valid to produce a zip file that contains timestamps encoded in + the Unix format as well as in the Windows format, in addition to the LastModified time attached to each + entry in the archive, a time that is always stored in "DOS format". And, + notwithstanding the names PKWare uses for these time formats, any of them + can be read and written by any computer, on any operating system. But, + there are no guarantees that a program running on Mac or Linux will + gracefully handle a zip file with "Windows" formatted times, or that an + application that does not use DotNetZip but runs on Windows will be able to + handle file times in Unix format. + + + + When in doubt, test. Sorry, I haven't got a complete list of tools and + which sort of timestamps they can use and will tolerate. If you get any + good information and would like to pass it on, please do so and I will + include that information in this documentation. + + + + + This example shows how to save a zip file that contains file timestamps + in a format normally used by Unix. + + using (var zip = new ZipFile()) + { + // produce a zip file the Mac will like + zip.EmitTimesInWindowsFormatWhenSaving = false; + zip.EmitTimesInUnixFormatWhenSaving = true; + zip.AddDirectory(directoryToZip, "files"); + zip.Save(outputFile); + } + + + + Using zip As New ZipFile + '' produce a zip file the Mac will like + zip.EmitTimesInWindowsFormatWhenSaving = False + zip.EmitTimesInUnixFormatWhenSaving = True + zip.AddDirectory(directoryToZip, "files") + zip.Save(outputFile) + End Using + + + + + + + + + Specifies whether the Creation, Access, and Modified times + for entries added to the zip file will be emitted in "Unix(tm) + format" when the zip archive is saved. + + + + + An application creating a zip archive can use this flag to explicitly + specify that the file times for the entries should or should not be stored + in the zip archive in the format used by Unix. By default this flag is + false, meaning the Unix-format times are not stored in the zip + archive. + + + + When adding an entry from a file or directory, the Creation (), Access (), and Modified () times for the given entry are + automatically set from the filesystem values. When adding an entry from a + stream or string, all three values are implicitly set to DateTime.Now. + Applications can also explicitly set those times by calling . + + + + PKWARE's + zip specification describes multiple ways to format these times in a + zip file. One is the format Windows applications normally use: 100ns ticks + since January 1, 1601 UTC. The other is a format Unix applications + typically use: seconds since January 1, 1970 UTC. Each format can be + stored in an "extra field" in the zip entry when saving the zip + archive. The former uses an extra field with a Header Id of 0x000A, while + the latter uses a header ID of 0x5455, although you probably don't need to + know that. + + + + Not all tools and libraries can interpret these fields. Windows + compressed folders is one that can read the Windows Format timestamps, + while I believe the Infozip + tools can read the Unix format timestamps. Some tools and libraries may be + able to read only one or the other. DotNetZip can read or write times in + either or both formats. + + + + The times stored are taken from , , and . + + + + This property is not mutually exclusive of the property. It is possible and + legal and valid to produce a zip file that contains timestamps encoded in + the Unix format as well as in the Windows format, in addition to the LastModified time attached to each + entry in the zip archive, a time that is always stored in "DOS + format". And, notwithstanding the names PKWare uses for these time + formats, any of them can be read and written by any computer, on any + operating system. But, there are no guarantees that a program running on + Mac or Linux will gracefully handle a zip file with "Windows" formatted + times, or that an application that does not use DotNetZip but runs on + Windows will be able to handle file times in Unix format. + + + + When in doubt, test. Sorry, I haven't got a complete list of tools and + which sort of timestamps they can use and will tolerate. If you get any + good information and would like to pass it on, please do so and I will + include that information in this documentation. + + + + + + + + + Indicates whether verbose output is sent to the during AddXxx() and + ReadXxx() operations. + + + + This is a synthetic property. It returns true if the is non-null. + + + + + Returns true if an entry by the given name exists in the ZipFile. + + + the name of the entry to find + true if an entry with the given name exists; otherwise false. + + + + + Indicates whether to perform case-sensitive matching on the filename when + retrieving entries in the zipfile via the string-based indexer. + + + + The default value is false, which means don't do case-sensitive + matching. In other words, retrieving zip["ReadMe.Txt"] is the same as + zip["readme.txt"]. It really makes sense to set this to true only + if you are not running on Windows, which has case-insensitive + filenames. But since this library is not built for non-Windows platforms, + in most cases you should just leave this property alone. + + + + + Indicates whether to ignore duplicate files (report only the first entry) + when loading a zipfile. + + + + The default value is false, which will try to make all files + available (duplicates will have a "copy" suffix appended to their name). + Setting this to true prior to using Initialize to read a + zipfile will prevent this and instead just ignore the duplicates. + + + + + Indicates whether to encode entry filenames and entry comments using Unicode + (UTF-8). + + + + + The + PKWare zip specification provides for encoding file names and file + comments in either the IBM437 code page, or in UTF-8. This flag selects + the encoding according to that specification. By default, this flag is + false, and filenames and comments are encoded into the zip file in the + IBM437 codepage. Setting this flag to true will specify that filenames + and comments that cannot be encoded with IBM437 will be encoded with + UTF-8. + + + + Zip files created with strict adherence to the PKWare specification with + respect to UTF-8 encoding can contain entries with filenames containing + any combination of Unicode characters, including the full range of + characters from Chinese, Latin, Hebrew, Greek, Cyrillic, and many other + alphabets. However, because at this time, the UTF-8 portion of the PKWare + specification is not broadly supported by other zip libraries and + utilities, such zip files may not be readable by your favorite zip tool or + archiver. In other words, interoperability will decrease if you set this + flag to true. + + + + In particular, Zip files created with strict adherence to the PKWare + specification with respect to UTF-8 encoding will not work well with + Explorer in Windows XP or Windows Vista, because Windows compressed + folders, as far as I know, do not support UTF-8 in zip files. Vista can + read the zip files, but shows the filenames incorrectly. Unpacking from + Windows Vista Explorer will result in filenames that have rubbish + characters in place of the high-order UTF-8 bytes. + + + + Also, zip files that use UTF-8 encoding will not work well with Java + applications that use the java.util.zip classes, as of v5.0 of the Java + runtime. The Java runtime does not correctly implement the PKWare + specification in this regard. + + + + As a result, we have the unfortunate situation that "correct" behavior by + the DotNetZip library with regard to Unicode encoding of filenames during + zip creation will result in zip files that are readable by strictly + compliant and current tools (for example the most recent release of the + commercial WinZip tool); but these zip files will not be readable by + various other tools or libraries, including Windows Explorer. + + + + The DotNetZip library can read and write zip files with UTF8-encoded + entries, according to the PKware spec. If you use DotNetZip for both + creating and reading the zip file, and you use UTF-8, there will be no + loss of information in the filenames. For example, using a self-extractor + created by this library will allow you to unpack files correctly with no + loss of information in the filenames. + + + + If you do not set this flag, it will remain false. If this flag is false, + your ZipFile will encode all filenames and comments using the + IBM437 codepage. This can cause "loss of information" on some filenames, + but the resulting zipfile will be more interoperable with other + utilities. As an example of the loss of information, diacritics can be + lost. The o-tilde character will be down-coded to plain o. The c with a + cedilla (Unicode 0xE7) used in Portugese will be downcoded to a c. + Likewise, the O-stroke character (Unicode 248), used in Danish and + Norwegian, will be down-coded to plain o. Chinese characters cannot be + represented in codepage IBM437; when using the default encoding, Chinese + characters in filenames will be represented as ?. These are all examples + of "information loss". + + + + The loss of information associated to the use of the IBM437 encoding is + inconvenient, and can also lead to runtime errors. For example, using + IBM437, any sequence of 4 Chinese characters will be encoded as ????. If + your application creates a ZipFile, then adds two files, each with + names of four Chinese characters each, this will result in a duplicate + filename exception. In the case where you add a single file with a name + containing four Chinese characters, calling Extract() on the entry that + has question marks in the filename will result in an exception, because + the question mark is not legal for use within filenames on Windows. These + are just a few examples of the problems associated to loss of information. + + + + This flag is independent of the encoding of the content within the entries + in the zip file. Think of the zip file as a container - it supports an + encoding. Within the container are other "containers" - the file entries + themselves. The encoding within those entries is independent of the + encoding of the zip archive container for those entries. + + + + Rather than specify the encoding in a binary fashion using this flag, an + application can specify an arbitrary encoding via the property. Setting the encoding + explicitly when creating zip archives will result in non-compliant zip + files that, curiously, are fairly interoperable. The challenge is, the + PKWare specification does not provide for a way to specify that an entry + in a zip archive uses a code page that is neither IBM437 nor UTF-8. + Therefore if you set the encoding explicitly when creating a zip archive, + you must take care upon reading the zip archive to use the same code page. + If you get it wrong, the behavior is undefined and may result in incorrect + filenames, exceptions, stomach upset, hair loss, and acne. + + + + + + + Specify whether to use ZIP64 extensions when saving a zip archive. + + + + + + When creating a zip file, the default value for the property is . is + safest, in the sense that you will not get an Exception if a pre-ZIP64 + limit is exceeded. + + + + You may set the property at any time before calling Save(). + + + + When reading a zip file via the Zipfile.Read() method, DotNetZip + will properly read ZIP64-endowed zip archives, regardless of the value of + this property. DotNetZip will always read ZIP64 archives. This property + governs only whether DotNetZip will write them. Therefore, when updating + archives, be careful about setting this property after reading an archive + that may use ZIP64 extensions. + + + + An interesting question is, if you have set this property to + AsNecessary, and then successfully saved, does the resulting + archive use ZIP64 extensions or not? To learn this, check the property, after calling Save(). + + + + Have you thought about + donating? + + + + + + + + Indicates whether the archive requires ZIP64 extensions. + + + + + + This property is null (or Nothing in VB) if the archive has + not been saved, and there are fewer than 65334 ZipEntry items + contained in the archive. + + + + The Value is true if any of the following four conditions holds: + the uncompressed size of any entry is larger than 0xFFFFFFFF; the + compressed size of any entry is larger than 0xFFFFFFFF; the relative + offset of any entry within the zip archive is larger than 0xFFFFFFFF; or + there are more than 65534 entries in the archive. (0xFFFFFFFF = + 4,294,967,295). The result may not be known until a Save() is attempted + on the zip archive. The Value of this + property may be set only AFTER one of the Save() methods has been called. + + + + If none of the four conditions holds, and the archive has been saved, then + the Value is false. + + + + A Value of false does not indicate that the zip archive, as saved, + does not use ZIP64. It merely indicates that ZIP64 is not required. An + archive may use ZIP64 even when not required if the property is set to , or if the property is set to and the output stream was not + seekable. Use the property to determine if + the most recent Save() method resulted in an archive that utilized + the ZIP64 extensions. + + + + + + + + + Indicates whether the most recent Save() operation used ZIP64 extensions. + + + + + The use of ZIP64 extensions within an archive is not always necessary, and + for interoperability concerns, it may be desired to NOT use ZIP64 if + possible. The property can be + set to use ZIP64 extensions only when necessary. In those cases, + Sometimes applications want to know whether a Save() actually used ZIP64 + extensions. Applications can query this read-only property to learn + whether ZIP64 has been used in a just-saved ZipFile. + + + + The value is null (or Nothing in VB) if the archive has not + been saved. + + + + Non-null values (HasValue is true) indicate whether ZIP64 + extensions were used during the most recent Save() operation. The + ZIP64 extensions may have been used as required by any particular entry + because of its uncompressed or compressed size, or because the archive is + larger than 4294967295 bytes, or because there are more than 65534 entries + in the archive, or because the UseZip64WhenSaving property was set + to , or because the + UseZip64WhenSaving property was set to and the output stream was not seekable. + The value of this property does not indicate the reason the ZIP64 + extensions were used. + + + + + + + + + Indicates whether the most recent Read() operation read a zip file that uses + ZIP64 extensions. + + + + This property will return null (Nothing in VB) if you've added an entry after reading + the zip file. + + + + + The text encoding to use when writing new entries to the ZipFile, + for those entries that cannot be encoded with the default (IBM437) + encoding; or, the text encoding that was used when reading the entries + from the ZipFile. + + + + + In its + zip specification, PKWare describes two options for encoding + filenames and comments: using IBM437 or UTF-8. But, some archiving tools + or libraries do not follow the specification, and instead encode + characters using the system default code page. For example, WinRAR when + run on a machine in Shanghai may encode filenames with the Big-5 Chinese + (950) code page. This behavior is contrary to the Zip specification, but + it occurs anyway. + + + + When using DotNetZip to write zip archives that will be read by one of + these other archivers, set this property to specify the code page to use + when encoding the and for each ZipEntry in the zip file, for + values that cannot be encoded with the default codepage for zip files, + IBM437. This is why this property is "provisional". In all cases, IBM437 + is used where possible, in other words, where no loss of data would + result. It is possible, therefore, to have a given entry with a + Comment encoded in IBM437 and a FileName encoded with the + specified "provisional" codepage. + + + + Be aware that a zip file created after you've explicitly set the property to a value other than + IBM437 may not be compliant to the PKWare specification, and may not be + readable by compliant archivers. On the other hand, many (most?) + archivers are non-compliant and can read zip files created in arbitrary + code pages. The trick is to use or specify the proper codepage when + reading the zip. + + + + When creating a zip archive using this library, it is possible to change + the value of between each + entry you add, and between adding entries and the call to + Save(). Don't do this. It will likely result in a zipfile that is + not readable. For best interoperability, either leave alone, or specify it only once, + before adding any entries to the ZipFile instance. There is one + exception to this recommendation, described later. + + + + When using an arbitrary, non-UTF8 code page for encoding, there is no + standard way for the creator application - whether DotNetZip, WinZip, + WinRar, or something else - to formally specify in the zip file which + codepage has been used for the entries. As a result, readers of zip files + are not able to inspect the zip file and determine the codepage that was + used for the entries contained within it. It is left to the application + or user to determine the necessary codepage when reading zip files encoded + this way. In other words, if you explicitly specify the codepage when you + create the zipfile, you must explicitly specify the same codepage when + reading the zipfile. + + + + The way you specify the code page to use when reading a zip file varies + depending on the tool or library you use to read the zip. In DotNetZip, + you use a ZipFile.Read() method that accepts an encoding parameter. It + isn't possible with Windows Explorer, as far as I know, to specify an + explicit codepage to use when reading a zip. If you use an incorrect + codepage when reading a zipfile, you will get entries with filenames that + are incorrect, and the incorrect filenames may even contain characters + that are not legal for use within filenames in Windows. Extracting entries + with illegal characters in the filenames will lead to exceptions. It's too + bad, but this is just the way things are with code pages in zip + files. Caveat Emptor. + + + + Example: Suppose you create a zipfile that contains entries with + filenames that have Danish characters. If you use equal to "iso-8859-1" (cp 28591), + the filenames will be correctly encoded in the zip. But, to read that + zipfile correctly, you have to specify the same codepage at the time you + read it. If try to read that zip file with Windows Explorer or another + application that is not flexible with respect to the codepage used to + decode filenames in zipfiles, you will get a filename like "Inf�.txt". + + + + When using DotNetZip to read a zip archive, and the zip archive uses an + arbitrary code page, you must specify the encoding to use before or when + the Zipfile is READ. This means you must use a ZipFile.Read() + method that allows you to specify a System.Text.Encoding parameter. Setting + the ProvisionalAlternateEncoding property after your application has read in + the zip archive will not affect the entry names of entries that have already + been read in. + + + + And now, the exception to the rule described above. One strategy for + specifying the code page for a given zip file is to describe the code page + in a human-readable form in the Zip comment. For example, the comment may + read "Entries in this archive are encoded in the Big5 code page". For + maximum interoperability, the zip comment in this case should be encoded + in the default, IBM437 code page. In this case, the zip comment is + encoded using a different page than the filenames. To do this, Specify + ProvisionalAlternateEncoding to your desired region-specific code + page, once before adding any entries, and then reset + ProvisionalAlternateEncoding to IBM437 before setting the property and calling Save(). + + + + + This example shows how to read a zip file using the Big-5 Chinese code page + (950), and extract each entry in the zip file. For this code to work as + desired, the Zipfile must have been created using the big5 code page + (CP950). This is typical, for example, when using WinRar on a machine with + CP950 set as the default code page. In that case, the names of entries + within the Zip archive will be stored in that code page, and reading the zip + archive must be done using that code page. If the application did not use + the correct code page in ZipFile.Read(), then names of entries within the + zip archive would not be correctly retrieved. + + using (var zip = ZipFile.Read(zipFileName, System.Text.Encoding.GetEncoding("big5"))) + { + // retrieve and extract an entry using a name encoded with CP950 + zip[MyDesiredEntry].Extract("unpack"); + } + + + + Using zip As ZipFile = ZipFile.Read(ZipToExtract, System.Text.Encoding.GetEncoding("big5")) + ' retrieve and extract an entry using a name encoded with CP950 + zip(MyDesiredEntry).Extract("unpack") + End Using + + + + DefaultEncoding + + + + A Text Encoding to use when encoding the filenames and comments for + all the ZipEntry items, during a ZipFile.Save() operation. + + + + Whether the encoding specified here is used during the save depends + on . + + + + + + A flag that tells if and when this instance should apply + AlternateEncoding to encode the filenames and comments associated to + of ZipEntry objects contained within this instance. + + + + + Gets or sets the TextWriter to which status messages are delivered + for the instance. + + + + If the TextWriter is set to a non-null value, then verbose output is sent + to the TextWriter during Add, Read, Save and + Extract operations. Typically, console applications might use + Console.Out and graphical or headless applications might use a + System.IO.StringWriter. The output of this is suitable for viewing + by humans. + + + + + In this example, a console application instantiates a ZipFile, then + sets the StatusMessageTextWriter to Console.Out. At that + point, all verbose status messages for that ZipFile are sent to the + console. + + + + using (ZipFile zip= ZipFile.Read(FilePath)) + { + zip.StatusMessageTextWriter= System.Console.Out; + // messages are sent to the console during extraction + zip.ExtractAll(); + } + + + + Using zip As ZipFile = ZipFile.Read(FilePath) + zip.StatusMessageTextWriter= System.Console.Out + 'Status Messages will be sent to the console during extraction + zip.ExtractAll() + End Using + + + + In this example, a Windows Forms application instantiates a + ZipFile, then sets the StatusMessageTextWriter to a + StringWriter. At that point, all verbose status messages for that + ZipFile are sent to the StringWriter. + + + + var sw = new System.IO.StringWriter(); + using (ZipFile zip= ZipFile.Read(FilePath)) + { + zip.StatusMessageTextWriter= sw; + zip.ExtractAll(); + } + Console.WriteLine("{0}", sw.ToString()); + + + + Dim sw as New System.IO.StringWriter + Using zip As ZipFile = ZipFile.Read(FilePath) + zip.StatusMessageTextWriter= sw + zip.ExtractAll() + End Using + 'Status Messages are now available in sw + + + + + + + Gets or sets the name for the folder to store the temporary file + this library writes when saving a zip archive. + + + + + This library will create a temporary file when saving a Zip archive to a + file. This file is written when calling one of the Save() methods + that does not save to a stream, or one of the SaveSelfExtractor() + methods. + + + + By default, the library will create the temporary file in the directory + specified for the file itself, via the property or via + the method. + + + + Setting this property allows applications to override this default + behavior, so that the library will create the temporary file in the + specified folder. For example, to have the library create the temporary + file in the current working directory, regardless where the ZipFile + is saved, specfy ".". To revert to the default behavior, set this + property to null (Nothing in VB). + + + + When setting the property to a non-null value, the folder specified must + exist; if it does not an exception is thrown. The application should have + write and delete permissions on the folder. The permissions are not + explicitly checked ahead of time; if the application does not have the + appropriate rights, an exception will be thrown at the time Save() + is called. + + + + There is no temporary file created when reading a zip archive. When + saving to a Stream, there is no temporary file created. For example, if + the application is an ASP.NET application and calls Save() + specifying the Response.OutputStream as the output stream, there is + no temporary file created. + + + + + Thrown when setting the property if the directory does not exist. + + + + + + Sets the password to be used on the ZipFile instance. + + + + + + When writing a zip archive, this password is applied to the entries, not + to the zip archive itself. It applies to any ZipEntry subsequently + added to the ZipFile, using one of the AddFile, + AddDirectory, AddEntry, or AddItem methods, etc. + When reading a zip archive, this property applies to any entry + subsequently extracted from the ZipFile using one of the Extract + methods on the ZipFile class. + + + + When writing a zip archive, keep this in mind: though the password is set + on the ZipFile object, according to the Zip spec, the "directory" of the + archive - in other words the list of entries or files contained in the archive - is + not encrypted with the password, or protected in any way. If you set the + Password property, the password actually applies to individual entries + that are added to the archive, subsequent to the setting of this property. + The list of filenames in the archive that is eventually created will + appear in clear text, but the contents of the individual files are + encrypted. This is how Zip encryption works. + + + + One simple way around this limitation is to simply double-wrap sensitive + filenames: Store the files in a zip file, and then store that zip file + within a second, "outer" zip file. If you apply a password to the outer + zip file, then readers will be able to see that the outer zip file + contains an inner zip file. But readers will not be able to read the + directory or file list of the inner zip file. + + + + If you set the password on the ZipFile, and then add a set of files + to the archive, then each entry is encrypted with that password. You may + also want to change the password between adding different entries. If you + set the password, add an entry, then set the password to null + (Nothing in VB), and add another entry, the first entry is + encrypted and the second is not. If you call AddFile(), then set + the Password property, then call ZipFile.Save, the file + added will not be password-protected, and no warning will be generated. + + + + When setting the Password, you may also want to explicitly set the property, to specify how to encrypt the entries added + to the ZipFile. If you set the Password to a non-null value and do not + set , then PKZip 2.0 ("Weak") encryption is used. + This encryption is relatively weak but is very interoperable. If you set + the password to a null value (Nothing in VB), Encryption is + reset to None. + + + + All of the preceding applies to writing zip archives, in other words when + you use one of the Save methods. To use this property when reading or an + existing ZipFile, do the following: set the Password property on the + ZipFile, then call one of the Extract() overloads on the . In this case, the entry is extracted using the + Password that is specified on the ZipFile instance. If you + have not set the Password property, then the password is + null, and the entry is extracted with no password. + + + + If you set the Password property on the ZipFile, then call + Extract() an entry that has not been encrypted with a password, the + password is not used for that entry, and the ZipEntry is extracted + as normal. In other words, the password is used only if necessary. + + + + The class also has a Password property. It takes precedence + over this property on the ZipFile. Typically, you would use the + per-entry Password when most entries in the zip archive use one password, + and a few entries use a different password. If all entries in the zip + file use the same password, then it is simpler to just set this property + on the ZipFile itself, whether creating a zip archive or extracting + a zip archive. + + + + + + + This example creates a zip file, using password protection for the + entries, and then extracts the entries from the zip file. When creating + the zip file, the Readme.txt file is not protected with a password, but + the other two are password-protected as they are saved. During extraction, + each file is extracted with the appropriate password. + + + // create a file with encryption + using (ZipFile zip = new ZipFile()) + { + zip.AddFile("ReadMe.txt"); + zip.Password= "!Secret1"; + zip.AddFile("MapToTheSite-7440-N49th.png"); + zip.AddFile("2008-Regional-Sales-Report.pdf"); + zip.Save("EncryptedArchive.zip"); + } + + // extract entries that use encryption + using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip")) + { + zip.Password= "!Secret1"; + zip.ExtractAll("extractDir"); + } + + + + + Using zip As New ZipFile + zip.AddFile("ReadMe.txt") + zip.Password = "123456!" + zip.AddFile("MapToTheSite-7440-N49th.png") + zip.Password= "!Secret1"; + zip.AddFile("2008-Regional-Sales-Report.pdf") + zip.Save("EncryptedArchive.zip") + End Using + + + ' extract entries that use encryption + Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip")) + zip.Password= "!Secret1" + zip.ExtractAll("extractDir") + End Using + + + + + + ZipFile.Encryption + ZipEntry.Password + + + + The action the library should take when extracting a file that already + exists. + + + + + This property affects the behavior of the Extract methods (one of the + Extract() or ExtractWithPassword() overloads), when + extraction would would overwrite an existing filesystem file. If you do + not set this property, the library throws an exception when extracting an + entry would overwrite an existing file. + + + + This property has no effect when extracting to a stream, or when the file + to be extracted does not already exist. + + + + + + + The action the library should take when an error is encountered while + opening or reading files as they are saved into a zip archive. + + + + + Errors can occur as a file is being saved to the zip archive. For + example, the File.Open may fail, or a File.Read may fail, because of + lock conflicts or other reasons. + + + + The first problem might occur after having called AddDirectory() on a + directory that contains a Clipper .dbf file; the file is locked by + Clipper and cannot be opened for read by another process. An example of + the second problem might occur when trying to zip a .pst file that is in + use by Microsoft Outlook. Outlook locks a range on the file, which allows + other processes to open the file, but not read it in its entirety. + + + + This property tells DotNetZip what you would like to do in the case of + these errors. The primary options are: ZipErrorAction.Throw to + throw an exception (this is the default behavior if you don't set this + property); ZipErrorAction.Skip to Skip the file for which there + was an error and continue saving; ZipErrorAction.Retry to Retry + the entry that caused the problem; or + ZipErrorAction.InvokeErrorEvent to invoke an event handler. + + + + This property is implicitly set to ZipErrorAction.InvokeErrorEvent + if you add a handler to the event. If you set + this property to something other than + ZipErrorAction.InvokeErrorEvent, then the ZipError + event is implicitly cleared. What it means is you can set one or the + other (or neither), depending on what you want, but you never need to set + both. + + + + As with some other properties on the ZipFile class, like , , and , setting this property on a ZipFile + instance will cause the specified ZipErrorAction to be used on all + items that are subsequently added to the + ZipFile instance. If you set this property after you have added + items to the ZipFile, but before you have called Save(), + those items will not use the specified error handling action. + + + + If you want to handle any errors that occur with any entry in the zip + file in the same way, then set this property once, before adding any + entries to the zip archive. + + + + If you set this property to ZipErrorAction.Skip and you'd like to + learn which files may have been skipped after a Save(), you can + set the on the ZipFile before + calling Save(). A message will be emitted into that writer for + each skipped file, if any. + + + + + + This example shows how to tell DotNetZip to skip any files for which an + error is generated during the Save(). + + Public Sub SaveZipFile() + Dim SourceFolder As String = "fodder" + Dim DestFile As String = "eHandler.zip" + Dim sw as New StringWriter + Using zipArchive As ZipFile = New ZipFile + ' Tell DotNetZip to skip any files for which it encounters an error + zipArchive.ZipErrorAction = ZipErrorAction.Skip + zipArchive.StatusMessageTextWriter = sw + zipArchive.AddDirectory(SourceFolder) + zipArchive.Save(DestFile) + End Using + ' examine sw here to see any messages + End Sub + + + + + + + + + + The Encryption to use for entries added to the ZipFile. + + + + + Set this when creating a zip archive, or when updating a zip archive. The + specified Encryption is applied to the entries subsequently added to the + ZipFile instance. Applications do not need to set the + Encryption property when reading or extracting a zip archive. + + + + If you set this to something other than EncryptionAlgorithm.None, you + will also need to set the . + + + + As with some other properties on the ZipFile class, like and , setting this + property on a ZipFile instance will cause the specified + EncryptionAlgorithm to be used on all items + that are subsequently added to the ZipFile instance. In other + words, if you set this property after you have added items to the + ZipFile, but before you have called Save(), those items will + not be encrypted or protected with a password in the resulting zip + archive. To get a zip archive with encrypted entries, set this property, + along with the property, before calling + AddFile, AddItem, or AddDirectory (etc.) on the + ZipFile instance. + + + + If you read a ZipFile, you can modify the Encryption on an + encrypted entry, only by setting the Encryption property on the + ZipEntry itself. Setting the Encryption property on the + ZipFile, once it has been created via a call to + ZipFile.Read(), does not affect entries that were previously read. + + + + For example, suppose you read a ZipFile, and there is an encrypted + entry. Setting the Encryption property on that ZipFile and + then calling Save() on the ZipFile does not update the + Encryption used for the entries in the archive. Neither is an + exception thrown. Instead, what happens during the Save() is that + all previously existing entries are copied through to the new zip archive, + with whatever encryption and password that was used when originally + creating the zip archive. Upon re-reading that archive, to extract + entries, applications should use the original password or passwords, if + any. + + + + Suppose an application reads a ZipFile, and there is an encrypted + entry. Setting the Encryption property on that ZipFile and + then adding new entries (via AddFile(), AddEntry(), etc) + and then calling Save() on the ZipFile does not update the + Encryption on any of the entries that had previously been in the + ZipFile. The Encryption property applies only to the + newly-added entries. + + + + + + + This example creates a zip archive that uses encryption, and then extracts + entries from the archive. When creating the zip archive, the ReadMe.txt + file is zipped without using a password or encryption. The other files + use encryption. + + + + // Create a zip archive with AES Encryption. + using (ZipFile zip = new ZipFile()) + { + zip.AddFile("ReadMe.txt"); + zip.Encryption= EncryptionAlgorithm.WinZipAes256; + zip.Password= "Top.Secret.No.Peeking!"; + zip.AddFile("7440-N49th.png"); + zip.AddFile("2008-Regional-Sales-Report.pdf"); + zip.Save("EncryptedArchive.zip"); + } + + // Extract a zip archive that uses AES Encryption. + // You do not need to specify the algorithm during extraction. + using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip")) + { + zip.Password= "Top.Secret.No.Peeking!"; + zip.ExtractAll("extractDirectory"); + } + + + + ' Create a zip that uses Encryption. + Using zip As New ZipFile() + zip.Encryption= EncryptionAlgorithm.WinZipAes256 + zip.Password= "Top.Secret.No.Peeking!" + zip.AddFile("ReadMe.txt") + zip.AddFile("7440-N49th.png") + zip.AddFile("2008-Regional-Sales-Report.pdf") + zip.Save("EncryptedArchive.zip") + End Using + + ' Extract a zip archive that uses AES Encryption. + ' You do not need to specify the algorithm during extraction. + Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip")) + zip.Password= "Top.Secret.No.Peeking!" + zip.ExtractAll("extractDirectory") + End Using + + + + + ZipFile.Password + ZipEntry.Encryption + + + + A callback that allows the application to specify the compression level + to use for entries subsequently added to the zip archive. + + + + + + With this callback, the DotNetZip library allows the application to + determine whether compression will be used, at the time of the + Save. This may be useful if the application wants to favor + speed over size, and wants to defer the decision until the time of + Save. + + + + Typically applications set the property on + the ZipFile or on each ZipEntry to determine the level of + compression used. This is done at the time the entry is added to the + ZipFile. Setting the property to + Ionic.Zlib.CompressionLevel.None means no compression will be used. + + + + This callback allows the application to defer the decision on the + CompressionLevel to use, until the time of the call to + ZipFile.Save(). The callback is invoked once per ZipEntry, + at the time the data for the entry is being written out as part of a + Save() operation. The application can use whatever criteria it + likes in determining the level to return. For example, an application may + wish that no .mp3 files should be compressed, because they are already + compressed and the extra compression is not worth the CPU time incurred, + and so can return None for all .mp3 entries. + + + + The library determines whether compression will be attempted for an entry + this way: If the entry is a zero length file, or a directory, no + compression is used. Otherwise, if this callback is set, it is invoked + and the CompressionLevel is set to the return value. If this + callback has not been set, then the previously set value for + CompressionLevel is used. + + + + + + + The maximum size of an output segment, when saving a split Zip file. + + + + Make sure you do not read from this field if you've set the value using + + + + Set this to a non-zero value before calling or to specify that the ZipFile should be saved as a + split archive, also sometimes called a spanned archive. Some also + call them multi-file archives. + + + + A split zip archive is saved in a set of discrete filesystem files, + rather than in a single file. This is handy when transmitting the + archive in email or some other mechanism that has a limit to the size of + each file. The first file in a split archive will be named + basename.z01, the second will be named basename.z02, and + so on. The final file is named basename.zip. According to the zip + specification from PKWare, the minimum value is 65536, for a 64k segment + size. The maximum number of segments allows in a split archive is 99. + + + + The value of this property determines the maximum size of a split + segment when writing a split archive. For example, suppose you have a + ZipFile that would save to a single file of 200k. If you set the + MaxOutputSegmentSize to 65536 before calling Save(), you + will get four distinct output files. On the other hand if you set this + property to 256k, then you will get a single-file archive for that + ZipFile. + + + + The size of each split output file will be as large as possible, up to + the maximum size set here. The zip specification requires that some data + fields in a zip archive may not span a split boundary, and an output + segment may be smaller than the maximum if necessary to avoid that + problem. Also, obviously the final segment of the archive may be smaller + than the maximum segment size. Segments will never be larger than the + value set with this property. + + + + You can save a split Zip file only when saving to a regular filesystem + file. It's not possible to save a split zip file as a self-extracting + archive, nor is it possible to save a split zip file to a stream. When + saving to a SFX or to a Stream, this property is ignored. + + + + About interoperability: Split or spanned zip files produced by DotNetZip + can be read by WinZip or PKZip, and vice-versa. Segmented zip files may + not be readable by other tools, if those other tools don't support zip + spanning or splitting. When in doubt, test. I don't believe Windows + Explorer can extract a split archive. + + + + This property has no effect when reading a split archive. You can read + a split archive in the normal way with DotNetZip. + + + + When saving a zip file, if you want a regular zip file rather than a + split zip file, don't set this property, or set it to Zero. + + + + If you read a split archive, with and + then subsequently call ZipFile.Save(), unless you set this + property before calling Save(), you will get a normal, + single-file archive. + + + + + + + + The maximum size of an output segment, when saving a split Zip file. + + + + If you set this value, make sure you do not accidently use in your code + + + + Set this to a non-zero value before calling or to specify that the ZipFile should be saved as a + split archive, also sometimes called a spanned archive. Some also + call them multi-file archives. + + + + A split zip archive is saved in a set of discrete filesystem files, + rather than in a single file. This is handy when transmitting the + archive in email or some other mechanism that has a limit to the size of + each file. The first file in a split archive will be named + basename.z01, the second will be named basename.z02, and + so on. The final file is named basename.zip. According to the zip + specification from PKWare, the minimum value is 65536, for a 64k segment + size. The maximum number of segments allows in a split archive is 99. + + + + The value of this property determines the maximum size of a split + segment when writing a split archive. For example, suppose you have a + ZipFile that would save to a single file of 200k. If you set the + MaxOutputSegmentSize to 65536 before calling Save(), you + will get four distinct output files. On the other hand if you set this + property to 256k, then you will get a single-file archive for that + ZipFile. + + + + The size of each split output file will be as large as possible, up to + the maximum size set here. The zip specification requires that some data + fields in a zip archive may not span a split boundary, and an output + segment may be smaller than the maximum if necessary to avoid that + problem. Also, obviously the final segment of the archive may be smaller + than the maximum segment size. Segments will never be larger than the + value set with this property. + + + + You can save a split Zip file only when saving to a regular filesystem + file. It's not possible to save a split zip file as a self-extracting + archive, nor is it possible to save a split zip file to a stream. When + saving to a SFX or to a Stream, this property is ignored. + + + + About interoperability: Split or spanned zip files produced by DotNetZip + can be read by WinZip or PKZip, and vice-versa. Segmented zip files may + not be readable by other tools, if those other tools don't support zip + spanning or splitting. When in doubt, test. I don't believe Windows + Explorer can extract a split archive. + + + + This property has no effect when reading a split archive. You can read + a split archive in the normal way with DotNetZip. + + + + When saving a zip file, if you want a regular zip file rather than a + split zip file, don't set this property, or set it to Zero. + + + + If you read a split archive, with and + then subsequently call ZipFile.Save(), unless you set this + property before calling Save(), you will get a normal, + single-file archive. + + + + + + + + Returns the number of segments used in the most recent Save() operation. + + + + This is normally zero, unless you have set the property. If you have set , and then you save a file, after the call to + Save() completes, you can read this value to learn the number of segments that + were created. + + + If you call Save("Archive.zip"), and it creates 5 segments, then you + will have filesystem files named Archive.z01, Archive.z02, Archive.z03, + Archive.z04, and Archive.zip, and the value of this property will be 5. + + + + + + + The size threshold for an entry, above which a parallel deflate is used. + + + + + + DotNetZip will use multiple threads to compress any ZipEntry, + if the entry is larger than the given size. Zero means "always + use parallel deflate", while -1 means "never use parallel + deflate". The default value for this property is 512k. Aside + from the special values of 0 and 1, the minimum value is 65536. + + + + If the entry size cannot be known before compression, as with a + read-forward stream, then Parallel deflate will never be + performed, unless the value of this property is zero. + + + + A parallel deflate operations will speed up the compression of + large files, on computers with multiple CPUs or multiple CPU + cores. For files above 1mb, on a dual core or dual-cpu (2p) + machine, the time required to compress the file can be 70% of the + single-threaded deflate. For very large files on 4p machines the + compression can be done in 30% of the normal time. The downside + is that parallel deflate consumes extra memory during the deflate, + and the deflation is not as effective. + + + + Parallel deflate tends to yield slightly less compression when + compared to as single-threaded deflate; this is because the original + data stream is split into multiple independent buffers, each of which + is compressed in parallel. But because they are treated + independently, there is no opportunity to share compression + dictionaries. For that reason, a deflated stream may be slightly + larger when compressed using parallel deflate, as compared to a + traditional single-threaded deflate. Sometimes the increase over the + normal deflate is as much as 5% of the total compressed size. For + larger files it can be as small as 0.1%. + + + + Multi-threaded compression does not give as much an advantage when + using Encryption. This is primarily because encryption tends to slow + down the entire pipeline. Also, multi-threaded compression gives less + of an advantage when using lower compression levels, for example . You may have to + perform some tests to determine the best approach for your situation. + + + + + + + + + + The maximum number of buffer pairs to use when performing + parallel compression. + + + + + This property sets an upper limit on the number of memory + buffer pairs to create when performing parallel + compression. The implementation of the parallel + compression stream allocates multiple buffers to + facilitate parallel compression. As each buffer fills up, + the stream uses + ThreadPool.QueueUserWorkItem() to compress those + buffers in a background threadpool thread. After a buffer + is compressed, it is re-ordered and written to the output + stream. + + + + A higher number of buffer pairs enables a higher degree of + parallelism, which tends to increase the speed of compression on + multi-cpu computers. On the other hand, a higher number of buffer + pairs also implies a larger memory consumption, more active worker + threads, and a higher cpu utilization for any compression. This + property enables the application to limit its memory consumption and + CPU utilization behavior depending on requirements. + + + + For each compression "task" that occurs in parallel, there are 2 + buffers allocated: one for input and one for output. This property + sets a limit for the number of pairs. The total amount of storage + space allocated for buffering will then be (N*S*2), where N is the + number of buffer pairs, S is the size of each buffer (). By default, DotNetZip allocates 4 buffer + pairs per CPU core, so if your machine has 4 cores, and you retain + the default buffer size of 128k, then the + ParallelDeflateOutputStream will use 4 * 4 * 2 * 128kb of buffer + memory in total, or 4mb, in blocks of 128kb. If you then set this + property to 8, then the number will be 8 * 2 * 128kb of buffer + memory, or 2mb. + + + + CPU utilization will also go up with additional buffers, because a + larger number of buffer pairs allows a larger number of background + threads to compress in parallel. If you find that parallel + compression is consuming too much memory or CPU, you can adjust this + value downward. + + + + The default value is 16. Different values may deliver better or + worse results, depending on your priorities and the dynamic + performance characteristics of your storage and compute resources. + + + + This property is not the number of buffer pairs to use; it is an + upper limit. An illustration: Suppose you have an application that + uses the default value of this property (which is 16), and it runs + on a machine with 2 CPU cores. In that case, DotNetZip will allocate + 4 buffer pairs per CPU core, for a total of 8 pairs. The upper + limit specified by this property has no effect. + + + + The application can set this value at any time + before calling ZipFile.Save(). + + + + + + + + Provides a string representation of the instance. + a string representation of the instance. + + + + Returns the version number on the DotNetZip assembly. + + + + + This property is exposed as a convenience. Callers could also get the + version value by retrieving GetName().Version on the + System.Reflection.Assembly object pointing to the DotNetZip + assembly. But sometimes it is not clear which assembly is being loaded. + This property makes it clear. + + + This static property is primarily useful for diagnostic purposes. + + + + + + Creates a new ZipFile instance, using the specified filename. + + + + + Applications can use this constructor to create a new ZipFile for writing, + or to slurp in an existing zip archive for read and update purposes. + + + + To create a new zip archive, an application can call this constructor, + passing the name of a file that does not exist. The name may be a fully + qualified path. Then the application can add directories or files to the + ZipFile via AddDirectory(), AddFile(), AddItem() + and then write the zip archive to the disk by calling Save(). The + zip file is not actually opened and written to the disk until the + application calls ZipFile.Save(). At that point the new zip file + with the given name is created. + + + + If you won't know the name of the Zipfile until the time you call + ZipFile.Save(), or if you plan to save to a stream (which has no + name), then you should use the no-argument constructor. + + + + The application can also call this constructor to read an existing zip + archive. passing the name of a valid zip file that does exist. But, it's + better form to use the static method, + passing the name of the zip file, because using ZipFile.Read() in + your code communicates very clearly what you are doing. In either case, + the file is then read into the ZipFile instance. The app can then + enumerate the entries or can modify the zip file, for example adding + entries, removing entries, changing comments, and so on. + + + + One advantage to this parameterized constructor: it allows applications to + use the same code to add items to a zip archive, regardless of whether the + zip file exists. + + + + Instances of the ZipFile class are not multi-thread safe. You may + not party on a single instance with multiple threads. You may have + multiple threads that each use a distinct ZipFile instance, or you + can synchronize multi-thread access to a single instance. + + + + By the way, since DotNetZip is so easy to use, don't you think you should + donate $5 or $10? + + + + + + Thrown if name refers to an existing file that is not a valid zip file. + + + + This example shows how to create a zipfile, and add a few files into it. + + String ZipFileToCreate = "archive1.zip"; + String DirectoryToZip = "c:\\reports"; + using (ZipFile zip = new ZipFile()) + { + // Store all files found in the top level directory, into the zip archive. + String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip); + zip.AddFiles(filenames, "files"); + zip.Save(ZipFileToCreate); + } + + + + Dim ZipFileToCreate As String = "archive1.zip" + Dim DirectoryToZip As String = "c:\reports" + Using zip As ZipFile = New ZipFile() + Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip) + zip.AddFiles(filenames, "files") + zip.Save(ZipFileToCreate) + End Using + + + + The filename to use for the new zip archive. + + + + + Creates a new ZipFile instance, using the specified name for the + filename, and the specified Encoding. + + + + + See the documentation on the ZipFile + constructor that accepts a single string argument for basic + information on all the ZipFile constructors. + + + + The Encoding is used as the default alternate encoding for entries with + filenames or comments that cannot be encoded with the IBM437 code page. + This is equivalent to setting the property on the ZipFile + instance after construction. + + + + Instances of the ZipFile class are not multi-thread safe. You may + not party on a single instance with multiple threads. You may have + multiple threads that each use a distinct ZipFile instance, or you + can synchronize multi-thread access to a single instance. + + + + + + Thrown if name refers to an existing file that is not a valid zip file. + + + The filename to use for the new zip archive. + The Encoding is used as the default alternate + encoding for entries with filenames or comments that cannot be encoded + with the IBM437 code page. + + + + Create a zip file, without specifying a target filename or stream to save to. + + + + + See the documentation on the ZipFile + constructor that accepts a single string argument for basic + information on all the ZipFile constructors. + + + + After instantiating with this constructor and adding entries to the + archive, the application should call or + to save to a file or a + stream, respectively. The application can also set the + property and then call the no-argument method. (This + is the preferred approach for applications that use the library through + COM interop.) If you call the no-argument method + without having set the Name of the ZipFile, either through + the parameterized constructor or through the explicit property , the + Save() will throw, because there is no place to save the file. + + + Instances of the ZipFile class are not multi-thread safe. You may + have multiple threads that each use a distinct ZipFile instance, or + you can synchronize multi-thread access to a single instance. + + + + + This example creates a Zip archive called Backup.zip, containing all the files + in the directory DirectoryToZip. Files within subdirectories are not zipped up. + + using (ZipFile zip = new ZipFile()) + { + // Store all files found in the top level directory, into the zip archive. + // note: this code does not recurse subdirectories! + String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip); + zip.AddFiles(filenames, "files"); + zip.Save("Backup.zip"); + } + + + + Using zip As New ZipFile + ' Store all files found in the top level directory, into the zip archive. + ' note: this code does not recurse subdirectories! + Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip) + zip.AddFiles(filenames, "files") + zip.Save("Backup.zip") + End Using + + + + + + Create a zip file, specifying a text Encoding, but without specifying a + target filename or stream to save to. + + + + + See the documentation on the ZipFile + constructor that accepts a single string argument for basic + information on all the ZipFile constructors. + + + + + + The Encoding is used as the default alternate encoding for entries with + filenames or comments that cannot be encoded with the IBM437 code page. + + + + + Creates a new ZipFile instance, using the specified name for the + filename, and the specified status message writer. + + + + + See the documentation on the ZipFile + constructor that accepts a single string argument for basic + information on all the ZipFile constructors. + + + + This version of the constructor allows the caller to pass in a TextWriter, + to which verbose messages will be written during extraction or creation of + the zip archive. A console application may wish to pass + System.Console.Out to get messages on the Console. A graphical or headless + application may wish to capture the messages in a different + TextWriter, for example, a StringWriter, and then display + the messages in a TextBox, or generate an audit log of ZipFile operations. + + + + To encrypt the data for the files added to the ZipFile instance, + set the Password property after creating the ZipFile instance. + + + + Instances of the ZipFile class are not multi-thread safe. You may + not party on a single instance with multiple threads. You may have + multiple threads that each use a distinct ZipFile instance, or you + can synchronize multi-thread access to a single instance. + + + + + + Thrown if name refers to an existing file that is not a valid zip file. + + + + + using (ZipFile zip = new ZipFile("Backup.zip", Console.Out)) + { + // Store all files found in the top level directory, into the zip archive. + // note: this code does not recurse subdirectories! + // Status messages will be written to Console.Out + String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip); + zip.AddFiles(filenames); + zip.Save(); + } + + + + Using zip As New ZipFile("Backup.zip", Console.Out) + ' Store all files found in the top level directory, into the zip archive. + ' note: this code does not recurse subdirectories! + ' Status messages will be written to Console.Out + Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip) + zip.AddFiles(filenames) + zip.Save() + End Using + + + + The filename to use for the new zip archive. + A TextWriter to use for writing + verbose status messages. + + + + Creates a new ZipFile instance, using the specified name for the + filename, the specified status message writer, and the specified Encoding. + + + + + This constructor works like the ZipFile + constructor that accepts a single string argument. See that + reference for detail on what this constructor does. + + + + This version of the constructor allows the caller to pass in a + TextWriter, and an Encoding. The TextWriter will collect + verbose messages that are generated by the library during extraction or + creation of the zip archive. A console application may wish to pass + System.Console.Out to get messages on the Console. A graphical or + headless application may wish to capture the messages in a different + TextWriter, for example, a StringWriter, and then display + the messages in a TextBox, or generate an audit log of + ZipFile operations. + + + + The Encoding is used as the default alternate encoding for entries + with filenames or comments that cannot be encoded with the IBM437 code + page. This is a equivalent to setting the property on the ZipFile + instance after construction. + + + + To encrypt the data for the files added to the ZipFile instance, + set the Password property after creating the ZipFile + instance. + + + + Instances of the ZipFile class are not multi-thread safe. You may + not party on a single instance with multiple threads. You may have + multiple threads that each use a distinct ZipFile instance, or you + can synchronize multi-thread access to a single instance. + + + + + + Thrown if fileName refers to an existing file that is not a valid zip file. + + + The filename to use for the new zip archive. + A TextWriter to use for writing verbose + status messages. + + The Encoding is used as the default alternate encoding for entries with + filenames or comments that cannot be encoded with the IBM437 code page. + + + + + Initialize a ZipFile instance by reading in a zip file. + + + + + + This method is primarily useful from COM Automation environments, when + reading or extracting zip files. In COM, it is not possible to invoke + parameterized constructors for a class. A COM Automation application can + update a zip file by using the default (no argument) + constructor, then calling Initialize() to read the contents + of an on-disk zip archive into the ZipFile instance. + + + + .NET applications are encouraged to use the ZipFile.Read() methods + for better clarity. + + + + the name of the existing zip file to read in. + + + + This is an integer indexer into the Zip archive. + + + + + This property is read-only. + + + + Internally, the ZipEntry instances that belong to the + ZipFile are stored in a Dictionary. When you use this + indexer the first time, it creates a read-only + List<ZipEntry> from the Dictionary.Values Collection. + If at any time you modify the set of entries in the ZipFile, + either by adding an entry, removing an entry, or renaming an + entry, a new List will be created, and the numeric indexes for the + remaining entries may be different. + + + + This means you cannot rename any ZipEntry from + inside an enumeration of the zip file. + + + + The index value. + + + + + + The ZipEntry within the Zip archive at the specified index. If the + entry does not exist in the archive, this indexer throws. + + + + + + This is a name-based indexer into the Zip archive. + + + + + This property is read-only. + + + + The property on the ZipFile + determines whether retrieval via this indexer is done via case-sensitive + comparisons. By default, retrieval is not case sensitive. This makes + sense on Windows, in which filesystems are not case sensitive. + + + + Regardless of case-sensitivity, it is not always the case that + this[value].FileName == value. In other words, the FileName + property of the ZipEntry retrieved with this indexer, may or may + not be equal to the index value. + + + + This is because DotNetZip performs a normalization of filenames passed to + this indexer, before attempting to retrieve the item. That normalization + includes: removal of a volume letter and colon, swapping backward slashes + for forward slashes. So, zip["dir1\\entry1.txt"].FileName == + "dir1/entry.txt". + + + + Directory entries in the zip file may be retrieved via this indexer only + with names that have a trailing slash. DotNetZip automatically appends a + trailing slash to the names of any directory entries added to a zip. + + + + + + This example extracts only the entries in a zip file that are .txt files. + + using (ZipFile zip = ZipFile.Read("PackedDocuments.zip")) + { + foreach (string s1 in zip.EntryFilenames) + { + if (s1.EndsWith(".txt")) + zip[s1].Extract("textfiles"); + } + } + + + Using zip As ZipFile = ZipFile.Read("PackedDocuments.zip") + Dim s1 As String + For Each s1 In zip.EntryFilenames + If s1.EndsWith(".txt") Then + zip(s1).Extract("textfiles") + End If + Next + End Using + + + + + + Thrown if the caller attempts to assign a non-null value to the indexer. + + + + The name of the file, including any directory path, to retrieve from the + zip. The filename match is not case-sensitive by default; you can use the + property to change this behavior. The + pathname can use forward-slashes or backward slashes. + + + + The ZipEntry within the Zip archive, given by the specified + filename. If the named entry does not exist in the archive, this indexer + returns null (Nothing in VB). + + + + + + The list of filenames for the entries contained within the zip archive. + + + + According to the ZIP specification, the names of the entries use forward + slashes in pathnames. If you are scanning through the list, you may have + to swap forward slashes for backslashes. + + + + + + This example shows one way to test if a filename is already contained + within a zip archive. + + String zipFileToRead= "PackedDocuments.zip"; + string candidate = "DatedMaterial.xps"; + using (ZipFile zip = new ZipFile(zipFileToRead)) + { + if (zip.EntryFilenames.Contains(candidate)) + Console.WriteLine("The file '{0}' exists in the zip archive '{1}'", + candidate, + zipFileName); + else + Console.WriteLine("The file, '{0}', does not exist in the zip archive '{1}'", + candidate, + zipFileName); + Console.WriteLine(); + } + + + Dim zipFileToRead As String = "PackedDocuments.zip" + Dim candidate As String = "DatedMaterial.xps" + Using zip As ZipFile.Read(ZipFileToRead) + If zip.EntryFilenames.Contains(candidate) Then + Console.WriteLine("The file '{0}' exists in the zip archive '{1}'", _ + candidate, _ + zipFileName) + Else + Console.WriteLine("The file, '{0}', does not exist in the zip archive '{1}'", _ + candidate, _ + zipFileName) + End If + Console.WriteLine + End Using + + + + + The list of strings for the filenames contained within the Zip archive. + + + + + + Returns the readonly collection of entries in the Zip archive. + + + + + + If there are no entries in the current ZipFile, the value returned is a + non-null zero-element collection. If there are entries in the zip file, + the elements are returned in no particular order. + + + This is the implied enumerator on the ZipFile class. If you use a + ZipFile instance in a context that expects an enumerator, you will + get this collection. + + + + + + + Returns a readonly collection of entries in the Zip archive, sorted by FileName. + + + + If there are no entries in the current ZipFile, the value returned + is a non-null zero-element collection. If there are entries in the zip + file, the elements are returned sorted by the name of the entry. + + + + + This example fills a Windows Forms ListView with the entries in a zip file. + + + using (ZipFile zip = ZipFile.Read(zipFile)) + { + foreach (ZipEntry entry in zip.EntriesSorted) + { + ListViewItem item = new ListViewItem(n.ToString()); + n++; + string[] subitems = new string[] { + entry.FileName.Replace("/","\\"), + entry.LastModified.ToString("yyyy-MM-dd HH:mm:ss"), + entry.UncompressedSize.ToString(), + String.Format("{0,5:F0}%", entry.CompressionRatio), + entry.CompressedSize.ToString(), + (entry.UsesEncryption) ? "Y" : "N", + String.Format("{0:X8}", entry.Crc)}; + + foreach (String s in subitems) + { + ListViewItem.ListViewSubItem subitem = new ListViewItem.ListViewSubItem(); + subitem.Text = s; + item.SubItems.Add(subitem); + } + + this.listView1.Items.Add(item); + } + } + + + + + + + + Returns the number of entries in the Zip archive. + + + + + Removes the given ZipEntry from the zip archive. + + + + + After calling RemoveEntry, the application must call Save to + make the changes permanent. + + + + + Thrown if the specified ZipEntry does not exist in the ZipFile. + + + + In this example, all entries in the zip archive dating from before + December 31st, 2007, are removed from the archive. This is actually much + easier if you use the RemoveSelectedEntries method. But I needed an + example for RemoveEntry, so here it is. + + String ZipFileToRead = "ArchiveToModify.zip"; + System.DateTime Threshold = new System.DateTime(2007,12,31); + using (ZipFile zip = ZipFile.Read(ZipFileToRead)) + { + var EntriesToRemove = new System.Collections.Generic.List<ZipEntry>(); + foreach (ZipEntry e in zip) + { + if (e.LastModified < Threshold) + { + // We cannot remove the entry from the list, within the context of + // an enumeration of said list. + // So we add the doomed entry to a list to be removed later. + EntriesToRemove.Add(e); + } + } + + // actually remove the doomed entries. + foreach (ZipEntry zombie in EntriesToRemove) + zip.RemoveEntry(zombie); + + zip.Comment= String.Format("This zip archive was updated at {0}.", + System.DateTime.Now.ToString("G")); + + // save with a different name + zip.Save("Archive-Updated.zip"); + } + + + + Dim ZipFileToRead As String = "ArchiveToModify.zip" + Dim Threshold As New DateTime(2007, 12, 31) + Using zip As ZipFile = ZipFile.Read(ZipFileToRead) + Dim EntriesToRemove As New System.Collections.Generic.List(Of ZipEntry) + Dim e As ZipEntry + For Each e In zip + If (e.LastModified < Threshold) Then + ' We cannot remove the entry from the list, within the context of + ' an enumeration of said list. + ' So we add the doomed entry to a list to be removed later. + EntriesToRemove.Add(e) + End If + Next + + ' actually remove the doomed entries. + Dim zombie As ZipEntry + For Each zombie In EntriesToRemove + zip.RemoveEntry(zombie) + Next + zip.Comment = String.Format("This zip archive was updated at {0}.", DateTime.Now.ToString("G")) + 'save as a different name + zip.Save("Archive-Updated.zip") + End Using + + + + + The ZipEntry to remove from the zip. + + + + + + + + Removes the ZipEntry with the given filename from the zip archive. + + + + + After calling RemoveEntry, the application must call Save to + make the changes permanent. + + + + + + Thrown if the ZipFile is not updatable. + + + + Thrown if a ZipEntry with the specified filename does not exist in + the ZipFile. + + + + + This example shows one way to remove an entry with a given filename from + an existing zip archive. + + + String zipFileToRead= "PackedDocuments.zip"; + string candidate = "DatedMaterial.xps"; + using (ZipFile zip = ZipFile.Read(zipFileToRead)) + { + if (zip.EntryFilenames.Contains(candidate)) + { + zip.RemoveEntry(candidate); + zip.Comment= String.Format("The file '{0}' has been removed from this archive.", + Candidate); + zip.Save(); + } + } + + + Dim zipFileToRead As String = "PackedDocuments.zip" + Dim candidate As String = "DatedMaterial.xps" + Using zip As ZipFile = ZipFile.Read(zipFileToRead) + If zip.EntryFilenames.Contains(candidate) Then + zip.RemoveEntry(candidate) + zip.Comment = String.Format("The file '{0}' has been removed from this archive.", Candidate) + zip.Save + End If + End Using + + + + + The name of the file, including any directory path, to remove from the zip. + The filename match is not case-sensitive by default; you can use the + CaseSensitiveRetrieval property to change this behavior. The + pathname can use forward-slashes or backward slashes. + + + + + + Closes the read and write streams associated + to the ZipFile, if necessary. + + + + The Dispose() method is generally employed implicitly, via a using(..) {..} + statement. (Using...End Using in VB) If you do not employ a using + statement, insure that your application calls Dispose() explicitly. For + example, in a Powershell application, or an application that uses the COM + interop interface, you must call Dispose() explicitly. + + + + This example extracts an entry selected by name, from the Zip file to the + Console. + + using (ZipFile zip = ZipFile.Read(zipfile)) + { + foreach (ZipEntry e in zip) + { + if (WantThisEntry(e.FileName)) + zip.Extract(e.FileName, Console.OpenStandardOutput()); + } + } // Dispose() is called implicitly here. + + + + Using zip As ZipFile = ZipFile.Read(zipfile) + Dim e As ZipEntry + For Each e In zip + If WantThisEntry(e.FileName) Then + zip.Extract(e.FileName, Console.OpenStandardOutput()) + End If + Next + End Using ' Dispose is implicity called here + + + + + + Disposes any managed resources, if the flag is set, then marks the + instance disposed. This method is typically not called explicitly from + application code. + + + + Applications should call the no-arg Dispose method. + + + + indicates whether the method should dispose streams or not. + + + + + Default size of the buffer used for IO. + + + + + An event handler invoked when a Save() starts, before and after each + entry has been written to the archive, when a Save() completes, and + during other Save events. + + + + + Depending on the particular event, different properties on the parameter are set. The following + table summarizes the available EventTypes and the conditions under + which this event handler is invoked with a + SaveProgressEventArgs with the given EventType. + + + + + value of EntryType + Meaning and conditions + + + + ZipProgressEventType.Saving_Started + Fired when ZipFile.Save() begins. + + + + + ZipProgressEventType.Saving_BeforeSaveEntry + + Fired within ZipFile.Save(), just before writing data for each + particular entry. + + + + + ZipProgressEventType.Saving_AfterSaveEntry + + Fired within ZipFile.Save(), just after having finished writing data + for each particular entry. + + + + + ZipProgressEventType.Saving_Completed + Fired when ZipFile.Save() has completed. + + + + + ZipProgressEventType.Saving_AfterSaveTempArchive + + Fired after the temporary file has been created. This happens only + when saving to a disk file. This event will not be invoked when + saving to a stream. + + + + + ZipProgressEventType.Saving_BeforeRenameTempArchive + + Fired just before renaming the temporary file to the permanent + location. This happens only when saving to a disk file. This event + will not be invoked when saving to a stream. + + + + + ZipProgressEventType.Saving_AfterRenameTempArchive + + Fired just after renaming the temporary file to the permanent + location. This happens only when saving to a disk file. This event + will not be invoked when saving to a stream. + + + + + ZipProgressEventType.Saving_AfterCompileSelfExtractor + + Fired after a self-extracting archive has finished compiling. This + EventType is used only within SaveSelfExtractor(). + + + + + ZipProgressEventType.Saving_BytesRead + + Set during the save of a particular entry, to update progress of the + Save(). When this EventType is set, the BytesTransferred is the + number of bytes that have been read from the source stream. The + TotalBytesToTransfer is the number of bytes in the uncompressed + file. + + + + + + + + + This example uses an anonymous method to handle the + SaveProgress event, by updating a progress bar. + + + progressBar1.Value = 0; + progressBar1.Max = listbox1.Items.Count; + using (ZipFile zip = new ZipFile()) + { + // listbox1 contains a list of filenames + zip.AddFiles(listbox1.Items); + + // do the progress bar: + zip.SaveProgress += (sender, e) => { + if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry) { + progressBar1.PerformStep(); + } + }; + + zip.Save(fs); + } + + + + + This example uses a named method as the + SaveProgress event handler, to update the user, in a + console-based application. + + + static bool justHadByteUpdate= false; + public static void SaveProgress(object sender, SaveProgressEventArgs e) + { + if (e.EventType == ZipProgressEventType.Saving_Started) + Console.WriteLine("Saving: {0}", e.ArchiveName); + + else if (e.EventType == ZipProgressEventType.Saving_Completed) + { + justHadByteUpdate= false; + Console.WriteLine(); + Console.WriteLine("Done: {0}", e.ArchiveName); + } + + else if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry) + { + if (justHadByteUpdate) + Console.WriteLine(); + Console.WriteLine(" Writing: {0} ({1}/{2})", + e.CurrentEntry.FileName, e.EntriesSaved, e.EntriesTotal); + justHadByteUpdate= false; + } + + else if (e.EventType == ZipProgressEventType.Saving_EntryBytesRead) + { + if (justHadByteUpdate) + Console.SetCursorPosition(0, Console.CursorTop); + Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer, + e.BytesTransferred / (0.01 * e.TotalBytesToTransfer )); + justHadByteUpdate= true; + } + } + + public static ZipUp(string targetZip, string directory) + { + using (var zip = new ZipFile()) { + zip.SaveProgress += SaveProgress; + zip.AddDirectory(directory); + zip.Save(targetZip); + } + } + + + + + Public Sub ZipUp(ByVal targetZip As String, ByVal directory As String) + Using zip As ZipFile = New ZipFile + AddHandler zip.SaveProgress, AddressOf MySaveProgress + zip.AddDirectory(directory) + zip.Save(targetZip) + End Using + End Sub + + Private Shared justHadByteUpdate As Boolean = False + + Public Shared Sub MySaveProgress(ByVal sender As Object, ByVal e As SaveProgressEventArgs) + If (e.EventType Is ZipProgressEventType.Saving_Started) Then + Console.WriteLine("Saving: {0}", e.ArchiveName) + + ElseIf (e.EventType Is ZipProgressEventType.Saving_Completed) Then + justHadByteUpdate = False + Console.WriteLine + Console.WriteLine("Done: {0}", e.ArchiveName) + + ElseIf (e.EventType Is ZipProgressEventType.Saving_BeforeWriteEntry) Then + If justHadByteUpdate Then + Console.WriteLine + End If + Console.WriteLine(" Writing: {0} ({1}/{2})", e.CurrentEntry.FileName, e.EntriesSaved, e.EntriesTotal) + justHadByteUpdate = False + + ElseIf (e.EventType Is ZipProgressEventType.Saving_EntryBytesRead) Then + If justHadByteUpdate Then + Console.SetCursorPosition(0, Console.CursorTop) + End If + Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, _ + e.TotalBytesToTransfer, _ + (CDbl(e.BytesTransferred) / (0.01 * e.TotalBytesToTransfer))) + justHadByteUpdate = True + End If + End Sub + + + + + + This is a more complete example of using the SaveProgress + events in a Windows Forms application, with a + Thread object. + + + delegate void SaveEntryProgress(SaveProgressEventArgs e); + delegate void ButtonClick(object sender, EventArgs e); + + public class WorkerOptions + { + public string ZipName; + public string Folder; + public string Encoding; + public string Comment; + public int ZipFlavor; + public Zip64Option Zip64; + } + + private int _progress2MaxFactor; + private bool _saveCanceled; + private long _totalBytesBeforeCompress; + private long _totalBytesAfterCompress; + private Thread _workerThread; + + + private void btnZipup_Click(object sender, EventArgs e) + { + KickoffZipup(); + } + + private void btnCancel_Click(object sender, EventArgs e) + { + if (this.lblStatus.InvokeRequired) + { + this.lblStatus.Invoke(new ButtonClick(this.btnCancel_Click), new object[] { sender, e }); + } + else + { + _saveCanceled = true; + lblStatus.Text = "Canceled..."; + ResetState(); + } + } + + private void KickoffZipup() + { + _folderName = tbDirName.Text; + + if (_folderName == null || _folderName == "") return; + if (this.tbZipName.Text == null || this.tbZipName.Text == "") return; + + // check for existence of the zip file: + if (System.IO.File.Exists(this.tbZipName.Text)) + { + var dlgResult = MessageBox.Show(String.Format("The file you have specified ({0}) already exists." + + " Do you want to overwrite this file?", this.tbZipName.Text), + "Confirmation is Required", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (dlgResult != DialogResult.Yes) return; + System.IO.File.Delete(this.tbZipName.Text); + } + + _saveCanceled = false; + _nFilesCompleted = 0; + _totalBytesAfterCompress = 0; + _totalBytesBeforeCompress = 0; + this.btnOk.Enabled = false; + this.btnOk.Text = "Zipping..."; + this.btnCancel.Enabled = true; + lblStatus.Text = "Zipping..."; + + var options = new WorkerOptions + { + ZipName = this.tbZipName.Text, + Folder = _folderName, + Encoding = "ibm437" + }; + + if (this.comboBox1.SelectedIndex != 0) + { + options.Encoding = this.comboBox1.SelectedItem.ToString(); + } + + if (this.radioFlavorSfxCmd.Checked) + options.ZipFlavor = 2; + else if (this.radioFlavorSfxGui.Checked) + options.ZipFlavor = 1; + else options.ZipFlavor = 0; + + if (this.radioZip64AsNecessary.Checked) + options.Zip64 = Zip64Option.AsNecessary; + else if (this.radioZip64Always.Checked) + options.Zip64 = Zip64Option.Always; + else options.Zip64 = Zip64Option.Never; + + options.Comment = String.Format("Encoding:{0} || Flavor:{1} || ZIP64:{2}\r\nCreated at {3} || {4}\r\n", + options.Encoding, + FlavorToString(options.ZipFlavor), + options.Zip64.ToString(), + System.DateTime.Now.ToString("yyyy-MMM-dd HH:mm:ss"), + this.Text); + + if (this.tbComment.Text != TB_COMMENT_NOTE) + options.Comment += this.tbComment.Text; + + _workerThread = new Thread(this.DoSave); + _workerThread.Name = "Zip Saver thread"; + _workerThread.Start(options); + this.Cursor = Cursors.WaitCursor; + } + + + private void DoSave(Object p) + { + WorkerOptions options = p as WorkerOptions; + try + { + using (var zip1 = new ZipFile()) + { + zip1.ProvisionalAlternateEncoding = System.Text.Encoding.GetEncoding(options.Encoding); + zip1.Comment = options.Comment; + zip1.AddDirectory(options.Folder); + _entriesToZip = zip1.EntryFileNames.Count; + SetProgressBars(); + zip1.SaveProgress += this.zip1_SaveProgress; + + zip1.UseZip64WhenSaving = options.Zip64; + + if (options.ZipFlavor == 1) + zip1.SaveSelfExtractor(options.ZipName, SelfExtractorFlavor.WinFormsApplication); + else if (options.ZipFlavor == 2) + zip1.SaveSelfExtractor(options.ZipName, SelfExtractorFlavor.ConsoleApplication); + else + zip1.Save(options.ZipName); + } + } + catch (System.Exception exc1) + { + MessageBox.Show(String.Format("Exception while zipping: {0}", exc1.Message)); + btnCancel_Click(null, null); + } + } + + + + void zip1_SaveProgress(object sender, SaveProgressEventArgs e) + { + switch (e.EventType) + { + case ZipProgressEventType.Saving_AfterWriteEntry: + StepArchiveProgress(e); + break; + case ZipProgressEventType.Saving_EntryBytesRead: + StepEntryProgress(e); + break; + case ZipProgressEventType.Saving_Completed: + SaveCompleted(); + break; + case ZipProgressEventType.Saving_AfterSaveTempArchive: + // this event only occurs when saving an SFX file + TempArchiveSaved(); + break; + } + if (_saveCanceled) + e.Cancel = true; + } + + + + private void StepArchiveProgress(SaveProgressEventArgs e) + { + if (this.progressBar1.InvokeRequired) + { + this.progressBar1.Invoke(new SaveEntryProgress(this.StepArchiveProgress), new object[] { e }); + } + else + { + if (!_saveCanceled) + { + _nFilesCompleted++; + this.progressBar1.PerformStep(); + _totalBytesAfterCompress += e.CurrentEntry.CompressedSize; + _totalBytesBeforeCompress += e.CurrentEntry.UncompressedSize; + + // reset the progress bar for the entry: + this.progressBar2.Value = this.progressBar2.Maximum = 1; + + this.Update(); + } + } + } + + + private void StepEntryProgress(SaveProgressEventArgs e) + { + if (this.progressBar2.InvokeRequired) + { + this.progressBar2.Invoke(new SaveEntryProgress(this.StepEntryProgress), new object[] { e }); + } + else + { + if (!_saveCanceled) + { + if (this.progressBar2.Maximum == 1) + { + // reset + Int64 max = e.TotalBytesToTransfer; + _progress2MaxFactor = 0; + while (max > System.Int32.MaxValue) + { + max /= 2; + _progress2MaxFactor++; + } + this.progressBar2.Maximum = (int)max; + lblStatus.Text = String.Format("{0} of {1} files...({2})", + _nFilesCompleted + 1, _entriesToZip, e.CurrentEntry.FileName); + } + + int xferred = e.BytesTransferred >> _progress2MaxFactor; + + this.progressBar2.Value = (xferred >= this.progressBar2.Maximum) + ? this.progressBar2.Maximum + : xferred; + + this.Update(); + } + } + } + + private void SaveCompleted() + { + if (this.lblStatus.InvokeRequired) + { + this.lblStatus.Invoke(new MethodInvoker(this.SaveCompleted)); + } + else + { + lblStatus.Text = String.Format("Done, Compressed {0} files, {1:N0}% of original.", + _nFilesCompleted, (100.00 * _totalBytesAfterCompress) / _totalBytesBeforeCompress); + ResetState(); + } + } + + private void ResetState() + { + this.btnCancel.Enabled = false; + this.btnOk.Enabled = true; + this.btnOk.Text = "Zip it!"; + this.progressBar1.Value = 0; + this.progressBar2.Value = 0; + this.Cursor = Cursors.Default; + if (!_workerThread.IsAlive) + _workerThread.Join(); + } + + + + + + + + + + + An event handler invoked before, during, and after the reading of a zip archive. + + + + + Depending on the particular event being signaled, different properties on the + parameter are set. The following table + summarizes the available EventTypes and the conditions under which this + event handler is invoked with a ReadProgressEventArgs with the given EventType. + + + + + value of EntryType + Meaning and conditions + + + + ZipProgressEventType.Reading_Started + Fired just as ZipFile.Read() begins. Meaningful properties: ArchiveName. + + + + + ZipProgressEventType.Reading_Completed + Fired when ZipFile.Read() has completed. Meaningful properties: ArchiveName. + + + + + ZipProgressEventType.Reading_ArchiveBytesRead + Fired while reading, updates the number of bytes read for the entire archive. + Meaningful properties: ArchiveName, CurrentEntry, BytesTransferred, TotalBytesToTransfer. + + + + + ZipProgressEventType.Reading_BeforeReadEntry + Indicates an entry is about to be read from the archive. + Meaningful properties: ArchiveName, EntriesTotal. + + + + + ZipProgressEventType.Reading_AfterReadEntry + Indicates an entry has just been read from the archive. + Meaningful properties: ArchiveName, EntriesTotal, CurrentEntry. + + + + + + + + + + + + + An event handler invoked before, during, and after extraction of + entries in the zip archive. + + + + + Depending on the particular event, different properties on the parameter are set. The following + table summarizes the available EventTypes and the conditions under + which this event handler is invoked with a + ExtractProgressEventArgs with the given EventType. + + + + + value of EntryType + Meaning and conditions + + + + ZipProgressEventType.Extracting_BeforeExtractAll + + Set when ExtractAll() begins. The ArchiveName, Overwrite, and + ExtractLocation properties are meaningful. + + + + ZipProgressEventType.Extracting_AfterExtractAll + + Set when ExtractAll() has completed. The ArchiveName, Overwrite, + and ExtractLocation properties are meaningful. + + + + + ZipProgressEventType.Extracting_BeforeExtractEntry + + Set when an Extract() on an entry in the ZipFile has begun. + Properties that are meaningful: ArchiveName, EntriesTotal, + CurrentEntry, Overwrite, ExtractLocation, EntriesExtracted. + + + + + ZipProgressEventType.Extracting_AfterExtractEntry + + Set when an Extract() on an entry in the ZipFile has completed. + Properties that are meaningful: ArchiveName, EntriesTotal, + CurrentEntry, Overwrite, ExtractLocation, EntriesExtracted. + + + + + ZipProgressEventType.Extracting_EntryBytesWritten + + Set within a call to Extract() on an entry in the ZipFile, as data + is extracted for the entry. Properties that are meaningful: + ArchiveName, CurrentEntry, BytesTransferred, TotalBytesToTransfer. + + + + + ZipProgressEventType.Extracting_ExtractEntryWouldOverwrite + + Set within a call to Extract() on an entry in the ZipFile, when the + extraction would overwrite an existing file. This event type is used + only when ExtractExistingFileAction on the ZipFile or + ZipEntry is set to InvokeExtractProgressEvent. + + + + + + + + + + private static bool justHadByteUpdate = false; + public static void ExtractProgress(object sender, ExtractProgressEventArgs e) + { + if(e.EventType == ZipProgressEventType.Extracting_EntryBytesWritten) + { + if (justHadByteUpdate) + Console.SetCursorPosition(0, Console.CursorTop); + + Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer, + e.BytesTransferred / (0.01 * e.TotalBytesToTransfer )); + justHadByteUpdate = true; + } + else if(e.EventType == ZipProgressEventType.Extracting_BeforeExtractEntry) + { + if (justHadByteUpdate) + Console.WriteLine(); + Console.WriteLine("Extracting: {0}", e.CurrentEntry.FileName); + justHadByteUpdate= false; + } + } + + public static ExtractZip(string zipToExtract, string directory) + { + string TargetDirectory= "extract"; + using (var zip = ZipFile.Read(zipToExtract)) { + zip.ExtractProgress += ExtractProgress; + foreach (var e in zip1) + { + e.Extract(TargetDirectory, true); + } + } + } + + + + Public Shared Sub Main(ByVal args As String()) + Dim ZipToUnpack As String = "C1P3SML.zip" + Dim TargetDir As String = "ExtractTest_Extract" + Console.WriteLine("Extracting file {0} to {1}", ZipToUnpack, TargetDir) + Using zip1 As ZipFile = ZipFile.Read(ZipToUnpack) + AddHandler zip1.ExtractProgress, AddressOf MyExtractProgress + Dim e As ZipEntry + For Each e In zip1 + e.Extract(TargetDir, True) + Next + End Using + End Sub + + Private Shared justHadByteUpdate As Boolean = False + + Public Shared Sub MyExtractProgress(ByVal sender As Object, ByVal e As ExtractProgressEventArgs) + If (e.EventType = ZipProgressEventType.Extracting_EntryBytesWritten) Then + If ExtractTest.justHadByteUpdate Then + Console.SetCursorPosition(0, Console.CursorTop) + End If + Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer, (CDbl(e.BytesTransferred) / (0.01 * e.TotalBytesToTransfer))) + ExtractTest.justHadByteUpdate = True + ElseIf (e.EventType = ZipProgressEventType.Extracting_BeforeExtractEntry) Then + If ExtractTest.justHadByteUpdate Then + Console.WriteLine + End If + Console.WriteLine("Extracting: {0}", e.CurrentEntry.FileName) + ExtractTest.justHadByteUpdate = False + End If + End Sub + + + + + + + + + + An event handler invoked before, during, and after Adding entries to a zip archive. + + + + Adding a large number of entries to a zip file can take a long + time. For example, when calling on a + directory that contains 50,000 files, it could take 3 minutes or so. + This event handler allws an application to track the progress of the Add + operation, and to optionally cancel a lengthy Add operation. + + + + + + int _numEntriesToAdd= 0; + int _numEntriesAdded= 0; + void AddProgressHandler(object sender, AddProgressEventArgs e) + { + switch (e.EventType) + { + case ZipProgressEventType.Adding_Started: + Console.WriteLine("Adding files to the zip..."); + break; + case ZipProgressEventType.Adding_AfterAddEntry: + _numEntriesAdded++; + Console.WriteLine(String.Format("Adding file {0}/{1} :: {2}", + _numEntriesAdded, _numEntriesToAdd, e.CurrentEntry.FileName)); + break; + case ZipProgressEventType.Adding_Completed: + Console.WriteLine("Added all files"); + break; + } + } + + void CreateTheZip() + { + using (ZipFile zip = new ZipFile()) + { + zip.AddProgress += AddProgressHandler; + zip.AddDirectory(System.IO.Path.GetFileName(DirToZip)); + zip.Save(ZipFileToCreate); + } + } + + + + + + Private Sub AddProgressHandler(ByVal sender As Object, ByVal e As AddProgressEventArgs) + Select Case e.EventType + Case ZipProgressEventType.Adding_Started + Console.WriteLine("Adding files to the zip...") + Exit Select + Case ZipProgressEventType.Adding_AfterAddEntry + Console.WriteLine(String.Format("Adding file {0}", e.CurrentEntry.FileName)) + Exit Select + Case ZipProgressEventType.Adding_Completed + Console.WriteLine("Added all files") + Exit Select + End Select + End Sub + + Sub CreateTheZip() + Using zip as ZipFile = New ZipFile + AddHandler zip.AddProgress, AddressOf AddProgressHandler + zip.AddDirectory(System.IO.Path.GetFileName(DirToZip)) + zip.Save(ZipFileToCreate); + End Using + End Sub + + + + + + + + + + + + An event that is raised when an error occurs during open or read of files + while saving a zip archive. + + + + + Errors can occur as a file is being saved to the zip archive. For + example, the File.Open may fail, or a File.Read may fail, because of + lock conflicts or other reasons. If you add a handler to this event, + you can handle such errors in your own code. If you don't add a + handler, the library will throw an exception if it encounters an I/O + error during a call to Save(). + + + + Setting a handler implicitly sets to + ZipErrorAction.InvokeErrorEvent. + + + + The handler you add applies to all items that are + subsequently added to the ZipFile instance. If you set this + property after you have added items to the ZipFile, but before you + have called Save(), errors that occur while saving those items + will not cause the error handler to be invoked. + + + + If you want to handle any errors that occur with any entry in the zip + file using the same error handler, then add your error handler once, + before adding any entries to the zip archive. + + + + In the error handler method, you need to set the property on the + ZipErrorEventArgs.CurrentEntry. This communicates back to + DotNetZip what you would like to do with this particular error. Within + an error handler, if you set the ZipEntry.ZipErrorAction property + on the ZipEntry to ZipErrorAction.InvokeErrorEvent or if + you don't set it at all, the library will throw the exception. (It is the + same as if you had set the ZipEntry.ZipErrorAction property on the + ZipEntry to ZipErrorAction.Throw.) If you set the + ZipErrorEventArgs.Cancel to true, the entire Save() will be + canceled. + + + + In the case that you use ZipErrorAction.Skip, implying that + you want to skip the entry for which there's been an error, DotNetZip + tries to seek backwards in the output stream, and truncate all bytes + written on behalf of that particular entry. This works only if the + output stream is seekable. It will not work, for example, when using + ASPNET's Response.OutputStream. + + + + + + + This example shows how to use an event handler to handle + errors during save of the zip file. + + + public static void MyZipError(object sender, ZipErrorEventArgs e) + { + Console.WriteLine("Error saving {0}...", e.FileName); + Console.WriteLine(" Exception: {0}", e.exception); + ZipEntry entry = e.CurrentEntry; + string response = null; + // Ask the user whether he wants to skip this error or not + do + { + Console.Write("Retry, Skip, Throw, or Cancel ? (R/S/T/C) "); + response = Console.ReadLine(); + Console.WriteLine(); + + } while (response != null && + response[0]!='S' && response[0]!='s' && + response[0]!='R' && response[0]!='r' && + response[0]!='T' && response[0]!='t' && + response[0]!='C' && response[0]!='c'); + + e.Cancel = (response[0]=='C' || response[0]=='c'); + + if (response[0]=='S' || response[0]=='s') + entry.ZipErrorAction = ZipErrorAction.Skip; + else if (response[0]=='R' || response[0]=='r') + entry.ZipErrorAction = ZipErrorAction.Retry; + else if (response[0]=='T' || response[0]=='t') + entry.ZipErrorAction = ZipErrorAction.Throw; + } + + public void SaveTheFile() + { + string directoryToZip = "fodder"; + string directoryInArchive = "files"; + string zipFileToCreate = "Archive.zip"; + using (var zip = new ZipFile()) + { + // set the event handler before adding any entries + zip.ZipError += MyZipError; + zip.AddDirectory(directoryToZip, directoryInArchive); + zip.Save(zipFileToCreate); + } + } + + + + Private Sub MyZipError(ByVal sender As Object, ByVal e As Ionic.Zip.ZipErrorEventArgs) + ' At this point, the application could prompt the user for an action to take. + ' But in this case, this application will simply automatically skip the file, in case of error. + Console.WriteLine("Zip Error, entry {0}", e.CurrentEntry.FileName) + Console.WriteLine(" Exception: {0}", e.exception) + ' set the desired ZipErrorAction on the CurrentEntry to communicate that to DotNetZip + e.CurrentEntry.ZipErrorAction = Zip.ZipErrorAction.Skip + End Sub + + Public Sub SaveTheFile() + Dim directoryToZip As String = "fodder" + Dim directoryInArchive As String = "files" + Dim zipFileToCreate as String = "Archive.zip" + Using zipArchive As ZipFile = New ZipFile + ' set the event handler before adding any entries + AddHandler zipArchive.ZipError, AddressOf MyZipError + zipArchive.AddDirectory(directoryToZip, directoryInArchive) + zipArchive.Save(zipFileToCreate) + End Using + End Sub + + + + + + + + + Extracts all of the items in the zip archive, to the specified path in the + filesystem. The path can be relative or fully-qualified. + + + + + This method will extract all entries in the ZipFile to the + specified path. + + + + If an extraction of a file from the zip archive would overwrite an + existing file in the filesystem, the action taken is dictated by the + ExtractExistingFile property, which overrides any setting you may have + made on individual ZipEntry instances. By default, if you have not + set that property on the ZipFile instance, the entry will not + be extracted, the existing file will not be overwritten and an + exception will be thrown. To change this, set the property, or use the + overload that allows you to + specify an ExtractExistingFileAction parameter. + + + + The action to take when an extract would overwrite an existing file + applies to all entries. If you want to set this on a per-entry basis, + then you must use one of the ZipEntry.Extract methods. + + + + This method will send verbose output messages to the , if it is set on the ZipFile + instance. + + + + You may wish to take advantage of the ExtractProgress event. + + + + About timestamps: When extracting a file entry from a zip archive, the + extracted file gets the last modified time of the entry as stored in + the archive. The archive may also store extended file timestamp + information, including last accessed and created times. If these are + present in the ZipEntry, then the extracted file will also get + these times. + + + + A Directory entry is somewhat different. It will get the times as + described for a file entry, but, if there are file entries in the zip + archive that, when extracted, appear in the just-created directory, + then when those file entries are extracted, the last modified and last + accessed times of the directory will change, as a side effect. The + result is that after an extraction of a directory and a number of + files within the directory, the last modified and last accessed + timestamps on the directory will reflect the time that the last file + was extracted into the directory, rather than the time stored in the + zip archive for the directory. + + + + To compensate, when extracting an archive with ExtractAll, + DotNetZip will extract all the file and directory entries as described + above, but it will then make a second pass on the directories, and + reset the times on the directories to reflect what is stored in the + zip archive. + + + + This compensation is performed only within the context of an + ExtractAll. If you call ZipEntry.Extract on a directory + entry, the timestamps on directory in the filesystem will reflect the + times stored in the zip. If you then call ZipEntry.Extract on + a file entry, which is extracted into the directory, the timestamps on + the directory will be updated to the current time. + + + + + This example extracts all the entries in a zip archive file, to the + specified target directory. The extraction will overwrite any + existing files silently. + + + String TargetDirectory= "unpack"; + using(ZipFile zip= ZipFile.Read(ZipFileToExtract)) + { + zip.ExtractExistingFile= ExtractExistingFileAction.OverwriteSilently; + zip.ExtractAll(TargetDirectory); + } + + + + Dim TargetDirectory As String = "unpack" + Using zip As ZipFile = ZipFile.Read(ZipFileToExtract) + zip.ExtractExistingFile= ExtractExistingFileAction.OverwriteSilently + zip.ExtractAll(TargetDirectory) + End Using + + + + + + + + The path to which the contents of the zipfile will be extracted. + The path can be relative or fully-qualified. + + + + + + Extracts all of the items in the zip archive, to the specified path in the + filesystem, using the specified behavior when extraction would overwrite an + existing file. + + + + + + This method will extract all entries in the ZipFile to the specified + path. For an extraction that would overwrite an existing file, the behavior + is dictated by , which overrides any + setting you may have made on individual ZipEntry instances. + + + + The action to take when an extract would overwrite an existing file + applies to all entries. If you want to set this on a per-entry basis, + then you must use or one of the similar methods. + + + + Calling this method is equivalent to setting the property and then calling . + + + + This method will send verbose output messages to the + , if it is set on the ZipFile instance. + + + + + This example extracts all the entries in a zip archive file, to the + specified target directory. It does not overwrite any existing files. + + String TargetDirectory= "c:\\unpack"; + using(ZipFile zip= ZipFile.Read(ZipFileToExtract)) + { + zip.ExtractAll(TargetDirectory, ExtractExistingFileAction.DontOverwrite); + } + + + + Dim TargetDirectory As String = "c:\unpack" + Using zip As ZipFile = ZipFile.Read(ZipFileToExtract) + zip.ExtractAll(TargetDirectory, ExtractExistingFileAction.DontOverwrite) + End Using + + + + + The path to which the contents of the zipfile will be extracted. + The path can be relative or fully-qualified. + + + + The action to take if extraction would overwrite an existing file. + + + + + + Reads a zip file archive and returns the instance. + + + + + The stream is read using the default System.Text.Encoding, which is the + IBM437 codepage. + + + + + Thrown if the ZipFile cannot be read. The implementation of this method + relies on System.IO.File.OpenRead, which can throw a variety of exceptions, + including specific exceptions if a file is not found, an unauthorized access + exception, exceptions for poorly formatted filenames, and so on. + + + + The name of the zip archive to open. This can be a fully-qualified or relative + pathname. + + + . + + The instance read from the zip archive. + + + + + Reads a zip file archive from the named filesystem file using the + specified options. + + + + + This version of the Read() method allows the caller to pass + in a TextWriter an Encoding, via an instance of the + ReadOptions class. The ZipFile is read in using the + specified encoding for entries where UTF-8 encoding is not + explicitly specified. + + + + + + + This example shows how to read a zip file using the Big-5 Chinese + code page (950), and extract each entry in the zip file, while + sending status messages out to the Console. + + + + For this code to work as intended, the zipfile must have been + created using the big5 code page (CP950). This is typical, for + example, when using WinRar on a machine with CP950 set as the + default code page. In that case, the names of entries within the + Zip archive will be stored in that code page, and reading the zip + archive must be done using that code page. If the application did + not use the correct code page in ZipFile.Read(), then names of + entries within the zip archive would not be correctly retrieved. + + + + string zipToExtract = "MyArchive.zip"; + string extractDirectory = "extract"; + var options = new ReadOptions + { + StatusMessageWriter = System.Console.Out, + Encoding = System.Text.Encoding.GetEncoding(950) + }; + using (ZipFile zip = ZipFile.Read(zipToExtract, options)) + { + foreach (ZipEntry e in zip) + { + e.Extract(extractDirectory); + } + } + + + + + Dim zipToExtract as String = "MyArchive.zip" + Dim extractDirectory as String = "extract" + Dim options as New ReadOptions + options.Encoding = System.Text.Encoding.GetEncoding(950) + options.StatusMessageWriter = System.Console.Out + Using zip As ZipFile = ZipFile.Read(zipToExtract, options) + Dim e As ZipEntry + For Each e In zip + e.Extract(extractDirectory) + Next + End Using + + + + + + + + This example shows how to read a zip file using the default + code page, to remove entries that have a modified date before a given threshold, + sending status messages out to a StringWriter. + + + + var options = new ReadOptions + { + StatusMessageWriter = new System.IO.StringWriter() + }; + using (ZipFile zip = ZipFile.Read("PackedDocuments.zip", options)) + { + var Threshold = new DateTime(2007,7,4); + // We cannot remove the entry from the list, within the context of + // an enumeration of said list. + // So we add the doomed entry to a list to be removed later. + // pass 1: mark the entries for removal + var MarkedEntries = new System.Collections.Generic.List<ZipEntry>(); + foreach (ZipEntry e in zip) + { + if (e.LastModified < Threshold) + MarkedEntries.Add(e); + } + // pass 2: actually remove the entry. + foreach (ZipEntry zombie in MarkedEntries) + zip.RemoveEntry(zombie); + zip.Comment = "This archive has been updated."; + zip.Save(); + } + // can now use contents of sw, eg store in an audit log + + + + Dim options as New ReadOptions + options.StatusMessageWriter = New System.IO.StringWriter + Using zip As ZipFile = ZipFile.Read("PackedDocuments.zip", options) + Dim Threshold As New DateTime(2007, 7, 4) + ' We cannot remove the entry from the list, within the context of + ' an enumeration of said list. + ' So we add the doomed entry to a list to be removed later. + ' pass 1: mark the entries for removal + Dim MarkedEntries As New System.Collections.Generic.List(Of ZipEntry) + Dim e As ZipEntry + For Each e In zip + If (e.LastModified < Threshold) Then + MarkedEntries.Add(e) + End If + Next + ' pass 2: actually remove the entry. + Dim zombie As ZipEntry + For Each zombie In MarkedEntries + zip.RemoveEntry(zombie) + Next + zip.Comment = "This archive has been updated." + zip.Save + End Using + ' can now use contents of sw, eg store in an audit log + + + + + Thrown if the zipfile cannot be read. The implementation of + this method relies on System.IO.File.OpenRead, which + can throw a variety of exceptions, including specific + exceptions if a file is not found, an unauthorized access + exception, exceptions for poorly formatted filenames, and so + on. + + + + The name of the zip archive to open. + This can be a fully-qualified or relative pathname. + + + + The set of options to use when reading the zip file. + + + The ZipFile instance read from the zip archive. + + + + + + + Reads a zip file archive using the specified text encoding, the specified + TextWriter for status messages, and the specified ReadProgress event handler, + and returns the instance. + + + + The name of the zip archive to open. + This can be a fully-qualified or relative pathname. + + + + An event handler for Read operations. + + + + The System.IO.TextWriter to use for writing verbose status messages + during operations on the zip archive. A console application may wish to + pass System.Console.Out to get messages on the Console. A graphical + or headless application may wish to capture the messages in a different + TextWriter, such as a System.IO.StringWriter. + + + + The System.Text.Encoding to use when reading in the zip archive. Be + careful specifying the encoding. If the value you use here is not the same + as the Encoding used when the zip archive was created (possibly by a + different archiver) you will get unexpected results and possibly exceptions. + + + The instance read from the zip archive. + + + + + Reads a zip archive from a stream. + + + + + + When reading from a file, it's probably easier to just use + ZipFile.Read(String, ReadOptions). This + overload is useful when when the zip archive content is + available from an already-open stream. The stream must be + open and readable and seekable when calling this method. The + stream is left open when the reading is completed. + + + + Using this overload, the stream is read using the default + System.Text.Encoding, which is the IBM437 + codepage. If you want to specify the encoding to use when + reading the zipfile content, see + ZipFile.Read(Stream, ReadOptions). This + + + + Reading of zip content begins at the current position in the + stream. This means if you have a stream that concatenates + regular data and zip data, if you position the open, readable + stream at the start of the zip data, you will be able to read + the zip archive using this constructor, or any of the ZipFile + constructors that accept a as + input. Some examples of where this might be useful: the zip + content is concatenated at the end of a regular EXE file, as + some self-extracting archives do. (Note: SFX files produced + by DotNetZip do not work this way; they can be read as normal + ZIP files). Another example might be a stream being read from + a database, where the zip content is embedded within an + aggregate stream of data. + + + + + + + This example shows how to Read zip content from a stream, and + extract one entry into a different stream. In this example, + the filename "NameOfEntryInArchive.doc", refers only to the + name of the entry within the zip archive. A file by that + name is not created in the filesystem. The I/O is done + strictly with the given streams. + + + + using (ZipFile zip = ZipFile.Read(InputStream)) + { + zip.Extract("NameOfEntryInArchive.doc", OutputStream); + } + + + + Using zip as ZipFile = ZipFile.Read(InputStream) + zip.Extract("NameOfEntryInArchive.doc", OutputStream) + End Using + + + + the stream containing the zip data. + + The ZipFile instance read from the stream + + + + + Reads a zip file archive from the given stream using the + specified options. + + + + + + When reading from a file, it's probably easier to just use + ZipFile.Read(String, ReadOptions). This + overload is useful when when the zip archive content is + available from an already-open stream. The stream must be + open and readable and seekable when calling this method. The + stream is left open when the reading is completed. + + + + Reading of zip content begins at the current position in the + stream. This means if you have a stream that concatenates + regular data and zip data, if you position the open, readable + stream at the start of the zip data, you will be able to read + the zip archive using this constructor, or any of the ZipFile + constructors that accept a as + input. Some examples of where this might be useful: the zip + content is concatenated at the end of a regular EXE file, as + some self-extracting archives do. (Note: SFX files produced + by DotNetZip do not work this way; they can be read as normal + ZIP files). Another example might be a stream being read from + a database, where the zip content is embedded within an + aggregate stream of data. + + + + the stream containing the zip data. + + + The set of options to use when reading the zip file. + + + + Thrown if the zip archive cannot be read. + + + The ZipFile instance read from the stream. + + + + + + + Reads a zip archive from a stream, using the specified text Encoding, the + specified TextWriter for status messages, + and the specified ReadProgress event handler. + + + + + Reading of zip content begins at the current position in the stream. This + means if you have a stream that concatenates regular data and zip data, if + you position the open, readable stream at the start of the zip data, you + will be able to read the zip archive using this constructor, or any of the + ZipFile constructors that accept a as + input. Some examples of where this might be useful: the zip content is + concatenated at the end of a regular EXE file, as some self-extracting + archives do. (Note: SFX files produced by DotNetZip do not work this + way). Another example might be a stream being read from a database, where + the zip content is embedded within an aggregate stream of data. + + + + the stream containing the zip data. + + + The System.IO.TextWriter to which verbose status messages are written + during operations on the ZipFile. For example, in a console + application, System.Console.Out works, and will get a message for each entry + added to the ZipFile. If the TextWriter is null, no verbose messages + are written. + + + + The text encoding to use when reading entries that do not have the UTF-8 + encoding bit set. Be careful specifying the encoding. If the value you use + here is not the same as the Encoding used when the zip archive was created + (possibly by a different archiver) you will get unexpected results and + possibly exceptions. See the + property for more information. + + + + An event handler for Read operations. + + + an instance of ZipFile + + + + Checks the given file to see if it appears to be a valid zip file. + + + + + Calling this method is equivalent to calling with the testExtract parameter set to false. + + + + The file to check. + true if the file appears to be a zip file. + + + + Checks a file to see if it is a valid zip file. + + + + + This method opens the specified zip file, reads in the zip archive, + verifying the ZIP metadata as it reads. + + + + If everything succeeds, then the method returns true. If anything fails - + for example if an incorrect signature or CRC is found, indicating a + corrupt file, the the method returns false. This method also returns + false for a file that does not exist. + + + + If is true, as part of its check, this + method reads in the content for each entry, expands it, and checks CRCs. + This provides an additional check beyond verifying the zip header and + directory data. + + + + If is true, and if any of the zip entries + are protected with a password, this method will return false. If you want + to verify a ZipFile that has entries which are protected with a + password, you will need to do that manually. + + + + + The zip file to check. + true if the caller wants to extract each entry. + true if the file contains a valid zip file. + + + + Checks a stream to see if it contains a valid zip archive. + + + + + This method reads the zip archive contained in the specified stream, verifying + the ZIP metadata as it reads. If testExtract is true, this method also extracts + each entry in the archive, dumping all the bits into . + + + + If everything succeeds, then the method returns true. If anything fails - + for example if an incorrect signature or CRC is found, indicating a corrupt + file, the the method returns false. This method also returns false for a + file that does not exist. + + + + If testExtract is true, this method reads in the content for each + entry, expands it, and checks CRCs. This provides an additional check + beyond verifying the zip header data. + + + + If testExtract is true, and if any of the zip entries are protected + with a password, this method will return false. If you want to verify a + ZipFile that has entries which are protected with a password, you will need + to do that manually. + + + + + + The stream to check. + true if the caller wants to extract each entry. + true if the stream contains a valid zip archive. + + + + Delete file with retry on UnauthorizedAccessException. + + + + + When calling File.Delete() on a file that has been "recently" + created, the call sometimes fails with + UnauthorizedAccessException. This method simply retries the Delete 3 + times with a sleep between tries. + + + + the name of the file to be deleted + + + + Saves the Zip archive to a file, specified by the Name property of the + ZipFile. + + + + + The ZipFile instance is written to storage, typically a zip file + in a filesystem, only when the caller calls Save. In the typical + case, the Save operation writes the zip content to a temporary file, and + then renames the temporary file to the desired name. If necessary, this + method will delete a pre-existing file before the rename. + + + + The property is specified either explicitly, + or implicitly using one of the parameterized ZipFile constructors. For + COM Automation clients, the Name property must be set explicitly, + because COM Automation clients cannot call parameterized constructors. + + + + When using a filesystem file for the Zip output, it is possible to call + Save multiple times on the ZipFile instance. With each + call the zip content is re-written to the same output file. + + + + Data for entries that have been added to the ZipFile instance is + written to the output when the Save method is called. This means + that the input streams for those entries must be available at the time + the application calls Save. If, for example, the application + adds entries with AddEntry using a dynamically-allocated + MemoryStream, the memory stream must not have been disposed + before the call to Save. See the property for more discussion of the + availability requirements of the input stream for an entry, and an + approach for providing just-in-time stream lifecycle management. + + + + + + + + Thrown if you haven't specified a location or stream for saving the zip, + either in the constructor or by setting the Name property, or if you try + to save a regular zip archive to a filename with a .exe extension. + + + + Thrown if or is non-zero, and the number + of segments that would be generated for the spanned zip file during the + save operation exceeds 99. If this happens, you need to increase the + segment size. + + + + + + Save the file to a new zipfile, with the given name. + + + + + This method allows the application to explicitly specify the name of the zip + file when saving. Use this when creating a new zip file, or when + updating a zip archive. + + + + An application can also save a zip archive in several places by calling this + method multiple times in succession, with different filenames. + + + + The ZipFile instance is written to storage, typically a zip file in a + filesystem, only when the caller calls Save. The Save operation writes + the zip content to a temporary file, and then renames the temporary file + to the desired name. If necessary, this method will delete a pre-existing file + before the rename. + + + + + + Thrown if you specify a directory for the filename. + + + + The name of the zip archive to save to. Existing files will + be overwritten with great prejudice. + + + + This example shows how to create and Save a zip file. + + using (ZipFile zip = new ZipFile()) + { + zip.AddDirectory(@"c:\reports\January"); + zip.Save("January.zip"); + } + + + + Using zip As New ZipFile() + zip.AddDirectory("c:\reports\January") + zip.Save("January.zip") + End Using + + + + + + This example shows how to update a zip file. + + using (ZipFile zip = ZipFile.Read("ExistingArchive.zip")) + { + zip.AddFile("NewData.csv"); + zip.Save("UpdatedArchive.zip"); + } + + + + Using zip As ZipFile = ZipFile.Read("ExistingArchive.zip") + zip.AddFile("NewData.csv") + zip.Save("UpdatedArchive.zip") + End Using + + + + + + + Save the zip archive to the specified stream. + + + + + The ZipFile instance is written to storage - typically a zip file + in a filesystem, but using this overload, the storage can be anything + accessible via a writable stream - only when the caller calls Save. + + + + Use this method to save the zip content to a stream directly. A common + scenario is an ASP.NET application that dynamically generates a zip file + and allows the browser to download it. The application can call + Save(Response.OutputStream) to write a zipfile directly to the + output stream, without creating a zip file on the disk on the ASP.NET + server. + + + + Be careful when saving a file to a non-seekable stream, including + Response.OutputStream. When DotNetZip writes to a non-seekable + stream, the zip archive is formatted in such a way that may not be + compatible with all zip tools on all platforms. It's a perfectly legal + and compliant zip file, but some people have reported problems opening + files produced this way using the Mac OS archive utility. + + + + + + + This example saves the zipfile content into a MemoryStream, and + then gets the array of bytes from that MemoryStream. + + + using (var zip = new Ionic.Zip.ZipFile()) + { + zip.CompressionLevel= Ionic.Zlib.CompressionLevel.BestCompression; + zip.Password = "VerySecret."; + zip.Encryption = EncryptionAlgorithm.WinZipAes128; + zip.AddFile(sourceFileName); + MemoryStream output = new MemoryStream(); + zip.Save(output); + + byte[] zipbytes = output.ToArray(); + } + + + + + + This example shows a pitfall you should avoid. DO NOT read + from a stream, then try to save to the same stream. DO + NOT DO THIS: + + + + using (var fs = new FileStream(filename, FileMode.Open)) + { + using (var zip = Ionic.Zip.ZipFile.Read(inputStream)) + { + zip.AddEntry("Name1.txt", "this is the content"); + zip.Save(inputStream); // NO NO NO!! + } + } + + + + Better like this: + + + + using (var zip = Ionic.Zip.ZipFile.Read(filename)) + { + zip.AddEntry("Name1.txt", "this is the content"); + zip.Save(); // YES! + } + + + + + + The System.IO.Stream to write to. It must be + writable. If you created the ZipFile instance by calling + ZipFile.Read(), this stream must not be the same stream + you passed to ZipFile.Read(). + + + + + Adds to the ZipFile a set of files from the current working directory on + disk, that conform to the specified criteria. + + + + + This method selects files from the the current working directory matching + the specified criteria, and adds them to the ZipFile. + + + + Specify the criteria in statements of 3 elements: a noun, an operator, and + a value. Consider the string "name != *.doc" . The noun is "name". The + operator is "!=", implying "Not Equal". The value is "*.doc". That + criterion, in English, says "all files with a name that does not end in + the .doc extension." + + + + Supported nouns include "name" (or "filename") for the filename; "atime", + "mtime", and "ctime" for last access time, last modfied time, and created + time of the file, respectively; "attributes" (or "attrs") for the file + attributes; "size" (or "length") for the file length (uncompressed), and + "type" for the type of object, either a file or a directory. The + "attributes", "name" and "type" nouns both support = and != as operators. + The "size", "atime", "mtime", and "ctime" nouns support = and !=, and + >, >=, <, <= as well. The times are taken to be expressed in + local time. + + + + Specify values for the file attributes as a string with one or more of the + characters H,R,S,A,I,L in any order, implying file attributes of Hidden, + ReadOnly, System, Archive, NotContextIndexed, and ReparsePoint (symbolic + link) respectively. + + + + To specify a time, use YYYY-MM-DD-HH:mm:ss or YYYY/MM/DD-HH:mm:ss as the + format. If you omit the HH:mm:ss portion, it is assumed to be 00:00:00 + (midnight). + + + + The value for a size criterion is expressed in integer quantities of bytes, + kilobytes (use k or kb after the number), megabytes (m or mb), or gigabytes + (g or gb). + + + + The value for a name is a pattern to match against the filename, potentially + including wildcards. The pattern follows CMD.exe glob rules: * implies one + or more of any character, while ? implies one character. If the name + pattern contains any slashes, it is matched to the entire filename, + including the path; otherwise, it is matched against only the filename + without the path. This means a pattern of "*\*.*" matches all files one + directory level deep, while a pattern of "*.*" matches all files in all + directories. + + + + To specify a name pattern that includes spaces, use single quotes around the + pattern. A pattern of "'* *.*'" will match all files that have spaces in + the filename. The full criteria string for that would be "name = '* *.*'" . + + + + The value for a type criterion is either F (implying a file) or D (implying + a directory). + + + + Some examples: + + + + + criteria + Files retrieved + + + + name != *.xls + any file with an extension that is not .xls + + + + + name = *.mp3 + any file with a .mp3 extension. + + + + + *.mp3 + (same as above) any file with a .mp3 extension. + + + + + attributes = A + all files whose attributes include the Archive bit. + + + + + attributes != H + all files whose attributes do not include the Hidden bit. + + + + + mtime > 2009-01-01 + all files with a last modified time after January 1st, 2009. + + + + + size > 2gb + all files whose uncompressed size is greater than 2gb. + + + + + type = D + all directories in the filesystem. + + + + + + You can combine criteria with the conjunctions AND or OR. Using a string + like "name = *.txt AND size >= 100k" for the selectionCriteria retrieves + entries whose names end in .txt, and whose uncompressed size is greater than + or equal to 100 kilobytes. + + + + For more complex combinations of criteria, you can use parenthesis to group + clauses in the boolean logic. Without parenthesis, the precedence of the + criterion atoms is determined by order of appearance. Unlike the C# + language, the AND conjunction does not take precendence over the logical OR. + This is important only in strings that contain 3 or more criterion atoms. + In other words, "name = *.txt and size > 1000 or attributes = H" implies + "((name = *.txt AND size > 1000) OR attributes = H)" while "attributes = + H OR name = *.txt and size > 1000" evaluates to "((attributes = H OR name + = *.txt) AND size > 1000)". When in doubt, use parenthesis. + + + + Using time properties requires some extra care. If you want to retrieve all + entries that were last updated on 2009 February 14, specify a time range + like so:"mtime >= 2009-02-14 AND mtime < 2009-02-15". Read this to + say: all files updated after 12:00am on February 14th, until 12:00am on + February 15th. You can use the same bracketing approach to specify any time + period - a year, a month, a week, and so on. + + + + The syntax allows one special case: if you provide a string with no spaces, it is + treated as a pattern to match for the filename. Therefore a string like "*.xls" + will be equivalent to specifying "name = *.xls". + + + + There is no logic in this method that insures that the file inclusion + criteria are internally consistent. For example, it's possible to specify + criteria that says the file must have a size of less than 100 bytes, as well + as a size that is greater than 1000 bytes. Obviously no file will ever + satisfy such criteria, but this method does not detect such logical + inconsistencies. The caller is responsible for insuring the criteria are + sensible. + + + + Using this method, the file selection does not recurse into + subdirectories, and the full path of the selected files is included in the + entries added into the zip archive. If you don't like these behaviors, + see the other overloads of this method. + + + + + This example zips up all *.csv files in the current working directory. + + using (ZipFile zip = new ZipFile()) + { + // To just match on filename wildcards, + // use the shorthand form of the selectionCriteria string. + zip.AddSelectedFiles("*.csv"); + zip.Save(PathToZipArchive); + } + + + Using zip As ZipFile = New ZipFile() + zip.AddSelectedFiles("*.csv") + zip.Save(PathToZipArchive) + End Using + + + + The criteria for file selection + + + + Adds to the ZipFile a set of files from the disk that conform to the + specified criteria, optionally recursing into subdirectories. + + + + + This method selects files from the the current working directory matching + the specified criteria, and adds them to the ZipFile. If + recurseDirectories is true, files are also selected from + subdirectories, and the directory structure in the filesystem is + reproduced in the zip archive, rooted at the current working directory. + + + + Using this method, the full path of the selected files is included in the + entries added into the zip archive. If you don't want this behavior, use + one of the overloads of this method that allows the specification of a + directoryInArchive. + + + + For details on the syntax for the selectionCriteria parameter, see . + + + + + + + This example zips up all *.xml files in the current working directory, or any + subdirectory, that are larger than 1mb. + + + using (ZipFile zip = new ZipFile()) + { + // Use a compound expression in the selectionCriteria string. + zip.AddSelectedFiles("name = *.xml and size > 1024kb", true); + zip.Save(PathToZipArchive); + } + + + Using zip As ZipFile = New ZipFile() + ' Use a compound expression in the selectionCriteria string. + zip.AddSelectedFiles("name = *.xml and size > 1024kb", true) + zip.Save(PathToZipArchive) + End Using + + + + The criteria for file selection + + + If true, the file selection will recurse into subdirectories. + + + + + Adds to the ZipFile a set of files from a specified directory in the + filesystem, that conform to the specified criteria. + + + + + This method selects files that conform to the specified criteria, from the + the specified directory on disk, and adds them to the ZipFile. The search + does not recurse into subdirectores. + + + + Using this method, the full filesystem path of the files on disk is + reproduced on the entries added to the zip file. If you don't want this + behavior, use one of the other overloads of this method. + + + + For details on the syntax for the selectionCriteria parameter, see . + + + + + + + This example zips up all *.xml files larger than 1mb in the directory + given by "d:\rawdata". + + + using (ZipFile zip = new ZipFile()) + { + // Use a compound expression in the selectionCriteria string. + zip.AddSelectedFiles("name = *.xml and size > 1024kb", "d:\\rawdata"); + zip.Save(PathToZipArchive); + } + + + + Using zip As ZipFile = New ZipFile() + ' Use a compound expression in the selectionCriteria string. + zip.AddSelectedFiles("name = *.xml and size > 1024kb", "d:\rawdata) + zip.Save(PathToZipArchive) + End Using + + + + The criteria for file selection + + + The name of the directory on the disk from which to select files. + + + + + Adds to the ZipFile a set of files from the specified directory on disk, + that conform to the specified criteria. + + + + + + This method selects files from the the specified disk directory matching + the specified selection criteria, and adds them to the ZipFile. If + recurseDirectories is true, files are also selected from + subdirectories. + + + + The full directory structure in the filesystem is reproduced on the + entries added to the zip archive. If you don't want this behavior, use + one of the overloads of this method that allows the specification of a + directoryInArchive. + + + + For details on the syntax for the selectionCriteria parameter, see . + + + + + + This example zips up all *.csv files in the "files" directory, or any + subdirectory, that have been saved since 2009 February 14th. + + + using (ZipFile zip = new ZipFile()) + { + // Use a compound expression in the selectionCriteria string. + zip.AddSelectedFiles("name = *.csv and mtime > 2009-02-14", "files", true); + zip.Save(PathToZipArchive); + } + + + Using zip As ZipFile = New ZipFile() + ' Use a compound expression in the selectionCriteria string. + zip.AddSelectedFiles("name = *.csv and mtime > 2009-02-14", "files", true) + zip.Save(PathToZipArchive) + End Using + + + + + This example zips up all files in the current working + directory, and all its child directories, except those in + the excludethis subdirectory. + + Using Zip As ZipFile = New ZipFile(zipfile) + Zip.AddSelectedFfiles("name != 'excludethis\*.*'", datapath, True) + Zip.Save() + End Using + + + + The criteria for file selection + + + The filesystem path from which to select files. + + + + If true, the file selection will recurse into subdirectories. + + + + + Adds to the ZipFile a selection of files from the specified directory on + disk, that conform to the specified criteria, and using a specified root + path for entries added to the zip archive. + + + + + This method selects files from the specified disk directory matching the + specified selection criteria, and adds those files to the ZipFile, using + the specified directory path in the archive. The search does not recurse + into subdirectories. For details on the syntax for the selectionCriteria + parameter, see . + + + + + + + This example zips up all *.psd files in the "photos" directory that have + been saved since 2009 February 14th, and puts them all in a zip file, + using the directory name of "content" in the zip archive itself. When the + zip archive is unzipped, the folder containing the .psd files will be + named "content". + + + using (ZipFile zip = new ZipFile()) + { + // Use a compound expression in the selectionCriteria string. + zip.AddSelectedFiles("name = *.psd and mtime > 2009-02-14", "photos", "content"); + zip.Save(PathToZipArchive); + } + + + Using zip As ZipFile = New ZipFile + zip.AddSelectedFiles("name = *.psd and mtime > 2009-02-14", "photos", "content") + zip.Save(PathToZipArchive) + End Using + + + + + The criteria for selection of files to add to the ZipFile. + + + + The path to the directory in the filesystem from which to select files. + + + + Specifies a directory path to use to in place of the + directoryOnDisk. This path may, or may not, correspond to a real + directory in the current filesystem. If the files within the zip are + later extracted, this is the path used for the extracted file. Passing + null (nothing in VB) will use the path on the file name, if any; in other + words it would use directoryOnDisk, plus any subdirectory. Passing + the empty string ("") will insert the item at the root path within the + archive. + + + + + Adds to the ZipFile a selection of files from the specified directory on + disk, that conform to the specified criteria, optionally recursing through + subdirectories, and using a specified root path for entries added to the + zip archive. + + + + This method selects files from the specified disk directory that match the + specified selection criteria, and adds those files to the ZipFile, using + the specified directory path in the archive. If recurseDirectories + is true, files are also selected from subdirectories, and the directory + structure in the filesystem is reproduced in the zip archive, rooted at + the directory specified by directoryOnDisk. For details on the + syntax for the selectionCriteria parameter, see . + + + + + This example zips up all files that are NOT *.pst files, in the current + working directory and any subdirectories. + + + using (ZipFile zip = new ZipFile()) + { + zip.AddSelectedFiles("name != *.pst", SourceDirectory, "backup", true); + zip.Save(PathToZipArchive); + } + + + Using zip As ZipFile = New ZipFile + zip.AddSelectedFiles("name != *.pst", SourceDirectory, "backup", true) + zip.Save(PathToZipArchive) + End Using + + + + + The criteria for selection of files to add to the ZipFile. + + + + The path to the directory in the filesystem from which to select files. + + + + Specifies a directory path to use to in place of the + directoryOnDisk. This path may, or may not, correspond to a real + directory in the current filesystem. If the files within the zip are + later extracted, this is the path used for the extracted file. Passing + null (nothing in VB) will use the path on the file name, if any; in other + words it would use directoryOnDisk, plus any subdirectory. Passing + the empty string ("") will insert the item at the root path within the + archive. + + + + If true, the method also scans subdirectories for files matching the + criteria. + + + + + Updates the ZipFile with a selection of files from the disk that conform + to the specified criteria. + + + + This method selects files from the specified disk directory that match the + specified selection criteria, and Updates the ZipFile with those + files, using the specified directory path in the archive. If + recurseDirectories is true, files are also selected from + subdirectories, and the directory structure in the filesystem is + reproduced in the zip archive, rooted at the directory specified by + directoryOnDisk. For details on the syntax for the + selectionCriteria parameter, see . + + + + The criteria for selection of files to add to the ZipFile. + + + + The path to the directory in the filesystem from which to select files. + + + + Specifies a directory path to use to in place of the + directoryOnDisk. This path may, or may not, correspond to a + real directory in the current filesystem. If the files within the zip + are later extracted, this is the path used for the extracted file. + Passing null (nothing in VB) will use the path on the file name, if + any; in other words it would use directoryOnDisk, plus any + subdirectory. Passing the empty string ("") will insert the item at + the root path within the archive. + + + + If true, the method also scans subdirectories for files matching the criteria. + + + + + + + Retrieve entries from the zipfile by specified criteria. + + + + + This method allows callers to retrieve the collection of entries from the zipfile + that fit the specified criteria. The criteria are described in a string format, and + can include patterns for the filename; constraints on the size of the entry; + constraints on the last modified, created, or last accessed time for the file + described by the entry; or the attributes of the entry. + + + + For details on the syntax for the selectionCriteria parameter, see . + + + + This method is intended for use with a ZipFile that has been read from storage. + When creating a new ZipFile, this method will work only after the ZipArchive has + been Saved to the disk (the ZipFile class subsequently and implicitly reads the Zip + archive from storage.) Calling SelectEntries on a ZipFile that has not yet been + saved will deliver undefined results. + + + + + Thrown if selectionCriteria has an invalid syntax. + + + + This example selects all the PhotoShop files from within an archive, and extracts them + to the current working directory. + + using (ZipFile zip1 = ZipFile.Read(ZipFileName)) + { + var PhotoShopFiles = zip1.SelectEntries("*.psd"); + foreach (ZipEntry psd in PhotoShopFiles) + { + psd.Extract(); + } + } + + + Using zip1 As ZipFile = ZipFile.Read(ZipFileName) + Dim PhotoShopFiles as ICollection(Of ZipEntry) + PhotoShopFiles = zip1.SelectEntries("*.psd") + Dim psd As ZipEntry + For Each psd In PhotoShopFiles + psd.Extract + Next + End Using + + + the string that specifies which entries to select + a collection of ZipEntry objects that conform to the inclusion spec + + + + Retrieve entries from the zipfile by specified criteria. + + + + + This method allows callers to retrieve the collection of entries from the zipfile + that fit the specified criteria. The criteria are described in a string format, and + can include patterns for the filename; constraints on the size of the entry; + constraints on the last modified, created, or last accessed time for the file + described by the entry; or the attributes of the entry. + + + + For details on the syntax for the selectionCriteria parameter, see . + + + + This method is intended for use with a ZipFile that has been read from storage. + When creating a new ZipFile, this method will work only after the ZipArchive has + been Saved to the disk (the ZipFile class subsequently and implicitly reads the Zip + archive from storage.) Calling SelectEntries on a ZipFile that has not yet been + saved will deliver undefined results. + + + + + Thrown if selectionCriteria has an invalid syntax. + + + + + using (ZipFile zip1 = ZipFile.Read(ZipFileName)) + { + var UpdatedPhotoShopFiles = zip1.SelectEntries("*.psd", "UpdatedFiles"); + foreach (ZipEntry e in UpdatedPhotoShopFiles) + { + // prompt for extract here + if (WantExtract(e.FileName)) + e.Extract(); + } + } + + + Using zip1 As ZipFile = ZipFile.Read(ZipFileName) + Dim UpdatedPhotoShopFiles As ICollection(Of ZipEntry) = zip1.SelectEntries("*.psd", "UpdatedFiles") + Dim e As ZipEntry + For Each e In UpdatedPhotoShopFiles + ' prompt for extract here + If Me.WantExtract(e.FileName) Then + e.Extract + End If + Next + End Using + + + the string that specifies which entries to select + + + the directory in the archive from which to select entries. If null, then + all directories in the archive are used. + + + a collection of ZipEntry objects that conform to the inclusion spec + + + + Remove entries from the zipfile by specified criteria. + + + + + This method allows callers to remove the collection of entries from the zipfile + that fit the specified criteria. The criteria are described in a string format, and + can include patterns for the filename; constraints on the size of the entry; + constraints on the last modified, created, or last accessed time for the file + described by the entry; or the attributes of the entry. + + + + For details on the syntax for the selectionCriteria parameter, see . + + + + This method is intended for use with a ZipFile that has been read from storage. + When creating a new ZipFile, this method will work only after the ZipArchive has + been Saved to the disk (the ZipFile class subsequently and implicitly reads the Zip + archive from storage.) Calling SelectEntries on a ZipFile that has not yet been + saved will deliver undefined results. + + + + + Thrown if selectionCriteria has an invalid syntax. + + + + This example removes all entries in a zip file that were modified prior to January 1st, 2008. + + using (ZipFile zip1 = ZipFile.Read(ZipFileName)) + { + // remove all entries from prior to Jan 1, 2008 + zip1.RemoveEntries("mtime < 2008-01-01"); + // don't forget to save the archive! + zip1.Save(); + } + + + Using zip As ZipFile = ZipFile.Read(ZipFileName) + ' remove all entries from prior to Jan 1, 2008 + zip1.RemoveEntries("mtime < 2008-01-01") + ' do not forget to save the archive! + zip1.Save + End Using + + + the string that specifies which entries to select + the number of entries removed + + + + Remove entries from the zipfile by specified criteria, and within the specified + path in the archive. + + + + + This method allows callers to remove the collection of entries from the zipfile + that fit the specified criteria. The criteria are described in a string format, and + can include patterns for the filename; constraints on the size of the entry; + constraints on the last modified, created, or last accessed time for the file + described by the entry; or the attributes of the entry. + + + + For details on the syntax for the selectionCriteria parameter, see . + + + + This method is intended for use with a ZipFile that has been read from storage. + When creating a new ZipFile, this method will work only after the ZipArchive has + been Saved to the disk (the ZipFile class subsequently and implicitly reads the Zip + archive from storage.) Calling SelectEntries on a ZipFile that has not yet been + saved will deliver undefined results. + + + + + Thrown if selectionCriteria has an invalid syntax. + + + + + using (ZipFile zip1 = ZipFile.Read(ZipFileName)) + { + // remove all entries from prior to Jan 1, 2008 + zip1.RemoveEntries("mtime < 2008-01-01", "documents"); + // a call to ZipFile.Save will make the modifications permanent + zip1.Save(); + } + + + Using zip As ZipFile = ZipFile.Read(ZipFileName) + ' remove all entries from prior to Jan 1, 2008 + zip1.RemoveEntries("mtime < 2008-01-01", "documents") + ' a call to ZipFile.Save will make the modifications permanent + zip1.Save + End Using + + + + the string that specifies which entries to select + + the directory in the archive from which to select entries. If null, then + all directories in the archive are used. + + the number of entries removed + + + + Selects and Extracts a set of Entries from the ZipFile. + + + + + The entries are extracted into the current working directory. + + + + If any of the files to be extracted already exist, then the action taken is as + specified in the property on the + corresponding ZipEntry instance. By default, the action taken in this case is to + throw an exception. + + + + For information on the syntax of the selectionCriteria string, + see . + + + + + This example shows how extract all XML files modified after 15 January 2009. + + using (ZipFile zip = ZipFile.Read(zipArchiveName)) + { + zip.ExtractSelectedEntries("name = *.xml and mtime > 2009-01-15"); + } + + + the selection criteria for entries to extract. + + + + + + Selects and Extracts a set of Entries from the ZipFile. + + + + + The entries are extracted into the current working directory. When extraction would would + overwrite an existing filesystem file, the action taken is as specified in the + parameter. + + + + For information on the syntax of the string describing the entry selection criteria, + see . + + + + + This example shows how extract all XML files modified after 15 January 2009, + overwriting any existing files. + + using (ZipFile zip = ZipFile.Read(zipArchiveName)) + { + zip.ExtractSelectedEntries("name = *.xml and mtime > 2009-01-15", + ExtractExistingFileAction.OverwriteSilently); + } + + + + the selection criteria for entries to extract. + + + The action to take if extraction would overwrite an existing file. + + + + + Selects and Extracts a set of Entries from the ZipFile. + + + + + The entries are selected from the specified directory within the archive, and then + extracted into the current working directory. + + + + If any of the files to be extracted already exist, then the action taken is as + specified in the property on the + corresponding ZipEntry instance. By default, the action taken in this case is to + throw an exception. + + + + For information on the syntax of the string describing the entry selection criteria, + see . + + + + + This example shows how extract all XML files modified after 15 January 2009, + and writes them to the "unpack" directory. + + using (ZipFile zip = ZipFile.Read(zipArchiveName)) + { + zip.ExtractSelectedEntries("name = *.xml and mtime > 2009-01-15","unpack"); + } + + + + the selection criteria for entries to extract. + + + the directory in the archive from which to select entries. If null, then + all directories in the archive are used. + + + + + + + Selects and Extracts a set of Entries from the ZipFile. + + + + + The entries are extracted into the specified directory. If any of the files to be + extracted already exist, an exception will be thrown. + + + For information on the syntax of the string describing the entry selection criteria, + see . + + + + the selection criteria for entries to extract. + + + the directory in the archive from which to select entries. If null, then + all directories in the archive are used. + + + + the directory on the disk into which to extract. It will be created + if it does not exist. + + + + + Selects and Extracts a set of Entries from the ZipFile. + + + + + The entries are extracted into the specified directory. When extraction would would + overwrite an existing filesystem file, the action taken is as specified in the + parameter. + + + + For information on the syntax of the string describing the entry selection criteria, + see . + + + + + This example shows how extract all files with an XML extension or with a size larger than 100,000 bytes, + and puts them in the unpack directory. For any files that already exist in + that destination directory, they will not be overwritten. + + using (ZipFile zip = ZipFile.Read(zipArchiveName)) + { + zip.ExtractSelectedEntries("name = *.xml or size > 100000", + null, + "unpack", + ExtractExistingFileAction.DontOverwrite); + } + + + + the selection criteria for entries to extract. + + + The directory on the disk into which to extract. It will be created if it does not exist. + + + + The directory in the archive from which to select entries. If null, then + all directories in the archive are used. + + + + The action to take if extraction would overwrite an existing file. + + + + + + + + Static constructor for ZipFile + + + Code Pages 437 and 1252 for English are same + Code Page 1252 Windows Latin 1 (ANSI) - + Code Page 437 MS-DOS Latin US - + + + + + The default text encoding used in zip archives. It is numeric 437, also + known as IBM437. + + + + + + Generic IEnumerator support, for use of a ZipFile in an enumeration. + + + + You probably do not want to call GetEnumerator explicitly. Instead + it is implicitly called when you use a loop in C#, or a + For Each loop in VB.NET. + + + + This example reads a zipfile of a given name, then enumerates the + entries in that zip file, and displays the information about each + entry on the Console. + + using (ZipFile zip = ZipFile.Read(zipfile)) + { + bool header = true; + foreach (ZipEntry e in zip) + { + if (header) + { + System.Console.WriteLine("Zipfile: {0}", zip.Name); + System.Console.WriteLine("Version Needed: 0x{0:X2}", e.VersionNeeded); + System.Console.WriteLine("BitField: 0x{0:X2}", e.BitField); + System.Console.WriteLine("Compression Method: 0x{0:X2}", e.CompressionMethod); + System.Console.WriteLine("\n{1,-22} {2,-6} {3,4} {4,-8} {0}", + "Filename", "Modified", "Size", "Ratio", "Packed"); + System.Console.WriteLine(new System.String('-', 72)); + header = false; + } + + System.Console.WriteLine("{1,-22} {2,-6} {3,4:F0}% {4,-8} {0}", + e.FileName, + e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"), + e.UncompressedSize, + e.CompressionRatio, + e.CompressedSize); + + e.Extract(); + } + } + + + + Dim ZipFileToExtract As String = "c:\foo.zip" + Using zip As ZipFile = ZipFile.Read(ZipFileToExtract) + Dim header As Boolean = True + Dim e As ZipEntry + For Each e In zip + If header Then + Console.WriteLine("Zipfile: {0}", zip.Name) + Console.WriteLine("Version Needed: 0x{0:X2}", e.VersionNeeded) + Console.WriteLine("BitField: 0x{0:X2}", e.BitField) + Console.WriteLine("Compression Method: 0x{0:X2}", e.CompressionMethod) + Console.WriteLine(ChrW(10) & "{1,-22} {2,-6} {3,4} {4,-8} {0}", _ + "Filename", "Modified", "Size", "Ratio", "Packed" ) + Console.WriteLine(New String("-"c, 72)) + header = False + End If + Console.WriteLine("{1,-22} {2,-6} {3,4:F0}% {4,-8} {0}", _ + e.FileName, _ + e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"), _ + e.UncompressedSize, _ + e.CompressionRatio, _ + e.CompressedSize ) + e.Extract + Next + End Using + + + + A generic enumerator suitable for use within a foreach loop. + + + + An IEnumerator, for use of a ZipFile in a foreach construct. + + + + This method is included for COM support. An application generally does not call + this method directly. It is called implicitly by COM clients when enumerating + the entries in the ZipFile instance. In VBScript, this is done with a For Each + statement. In Javascript, this is done with new Enumerator(zipfile). + + + + The IEnumerator over the entries in the ZipFile. + + + + + This class exposes a set of COM-accessible wrappers for static + methods available on the ZipFile class. You don't need this + class unless you are using DotNetZip from a COM environment. + + + + + A wrapper for ZipFile.IsZipFile(string) + + The filename to of the zip file to check. + true if the file contains a valid zip file. + + + + A wrapper for ZipFile.IsZipFile(string, bool) + + + We cannot use "overloaded" Method names in COM interop. + So, here, we use a unique name. + + The filename to of the zip file to check. + true if the file contains a valid zip file. + + + + A wrapper for ZipFile.CheckZip(string) + + The filename to of the zip file to check. + + true if the named zip file checks OK. Otherwise, false. + + + + A COM-friendly wrapper for the static method . + + + The filename to of the zip file to check. + + The password to check. + + true if the named zip file checks OK. Otherwise, false. + + + + A wrapper for ZipFile.FixZipDirectory(string) + + The filename to of the zip file to fix. + + + + A wrapper for ZipFile.LibraryVersion + + + the version number on the DotNetZip assembly, formatted as a string. + + + + + An enum that provides the various encryption algorithms supported by this + library. + + + + + + PkzipWeak implies the use of Zip 2.0 encryption, which is known to be + weak and subvertible. + + + + A note on interoperability: Values of PkzipWeak and None are + specified in PKWARE's zip + specification, and are considered to be "standard". Zip archives + produced using these options will be interoperable with many other zip tools + and libraries, including Windows Explorer. + + + + Values of WinZipAes128 and WinZipAes256 are not part of the Zip + specification, but rather imply the use of a vendor-specific extension from + WinZip. If you want to produce interoperable Zip archives, do not use these + values. For example, if you produce a zip archive using WinZipAes256, you + will be able to open it in Windows Explorer on Windows XP and Vista, but you + will not be able to extract entries; trying this will lead to an "unspecified + error". For this reason, some people have said that a zip archive that uses + WinZip's AES encryption is not actually a zip archive at all. A zip archive + produced this way will be readable with the WinZip tool (Version 11 and + beyond). + + + + There are other third-party tools and libraries, both commercial and + otherwise, that support WinZip's AES encryption. These will be able to read + AES-encrypted zip archives produced by DotNetZip, and conversely applications + that use DotNetZip to read zip archives will be able to read AES-encrypted + archives produced by those tools or libraries. Consult the documentation for + those other tools and libraries to find out if WinZip's AES encryption is + supported. + + + + In case you care: According to the WinZip specification, the + actual AES key used is derived from the via an + algorithm that complies with RFC 2898, using an iteration + count of 1000. The algorithm is sometimes referred to as PBKDF2, which stands + for "Password Based Key Derivation Function #2". + + + + A word about password strength and length: The AES encryption technology is + very good, but any system is only as secure as the weakest link. If you want + to secure your data, be sure to use a password that is hard to guess. To make + it harder to guess (increase its "entropy"), you should make it longer. If + you use normal characters from an ASCII keyboard, a password of length 20 will + be strong enough that it will be impossible to guess. For more information on + that, I'd encourage you to read this + article. + + + + + + + No encryption at all. + + + + + Traditional or Classic pkzip encryption. + + + + + WinZip AES encryption (128 key bits). + + + + + WinZip AES encryption (256 key bits). + + + + + An encryption algorithm that is not supported by DotNetZip. + + + + + Delegate in which the application writes the ZipEntry content for the named entry. + + + The name of the entry that must be written. + The stream to which the entry data should be written. + + + When you add an entry and specify a WriteDelegate, via , the application + code provides the logic that writes the entry data directly into the zip file. + + + + + This example shows how to define a WriteDelegate that obtains a DataSet, and then + writes the XML for the DataSet into the zip archive. There's no need to + save the XML to a disk file first. + + + private void WriteEntry (String filename, Stream output) + { + DataSet ds1 = ObtainDataSet(); + ds1.WriteXml(output); + } + + private void Run() + { + using (var zip = new ZipFile()) + { + zip.AddEntry(zipEntryName, WriteEntry); + zip.Save(zipFileName); + } + } + + + + Private Sub WriteEntry (ByVal filename As String, ByVal output As Stream) + DataSet ds1 = ObtainDataSet() + ds1.WriteXml(stream) + End Sub + + Public Sub Run() + Using zip = New ZipFile + zip.AddEntry(zipEntryName, New WriteDelegate(AddressOf WriteEntry)) + zip.Save(zipFileName) + End Using + End Sub + + + + + + + Delegate in which the application opens the stream, just-in-time, for the named entry. + + + + The name of the ZipEntry that the application should open the stream for. + + + + When you add an entry via , the application code provides the logic that + opens and closes the stream for the given ZipEntry. + + + + + + + Delegate in which the application closes the stream, just-in-time, for the named entry. + + + + The name of the ZipEntry that the application should close the stream for. + + + The stream to be closed. + + + When you add an entry via , the application code provides the logic that + opens and closes the stream for the given ZipEntry. + + + + + + + Delegate for the callback by which the application tells the + library the CompressionLevel to use for a file. + + + + + Using this callback, the application can, for example, specify that + previously-compressed files (.mp3, .png, .docx, etc) should use a + CompressionLevel of None, or can set the compression level based + on any other factor. + + + + + + + In an EventArgs type, indicates which sort of progress event is being + reported. + + + There are events for reading, events for saving, and events for + extracting. This enumeration allows a single EventArgs type to be sued to + describe one of multiple subevents. For example, a SaveProgress event is + invoked before, after, and during the saving of a single entry. The value + of an enum with this type, specifies which event is being triggered. The + same applies to Extraction, Reading and Adding events. + + + + + Indicates that a Add() operation has started. + + + + + Indicates that an individual entry in the archive has been added. + + + + + Indicates that a Add() operation has completed. + + + + + Indicates that a Read() operation has started. + + + + + Indicates that an individual entry in the archive is about to be read. + + + + + Indicates that an individual entry in the archive has just been read. + + + + + Indicates that a Read() operation has completed. + + + + + The given event reports the number of bytes read so far + during a Read() operation. + + + + + Indicates that a Save() operation has started. + + + + + Indicates that an individual entry in the archive is about to be written. + + + + + Indicates that an individual entry in the archive has just been saved. + + + + + Indicates that a Save() operation has completed. + + + + + Indicates that the zip archive has been created in a + temporary location during a Save() operation. + + + + + Indicates that the temporary file is about to be renamed to the final archive + name during a Save() operation. + + + + + Indicates that the temporary file is has just been renamed to the final archive + name during a Save() operation. + + + + + Indicates that the self-extracting archive has been compiled + during a Save() operation. + + + + + The given event is reporting the number of source bytes that have run through the compressor so far + during a Save() operation. + + + + + Indicates that an entry is about to be extracted. + + + + + Indicates that an entry has just been extracted. + + + + + Indicates that extraction of an entry would overwrite an existing + filesystem file. You must use + + ExtractExistingFileAction.InvokeExtractProgressEvent in the call + to ZipEntry.Extract() in order to receive this event. + + + + + The given event is reporting the number of bytes written so far for + the current entry during an Extract() operation. + + + + + Indicates that an ExtractAll operation is about to begin. + + + + + Indicates that an ExtractAll operation has completed. + + + + + Indicates that an error has occurred while saving a zip file. + This generally means the file cannot be opened, because it has been + removed, or because it is locked by another process. It can also + mean that the file cannot be Read, because of a range lock conflict. + + + + + Provides information about the progress of a save, read, or extract operation. + This is a base class; you will probably use one of the classes derived from this one. + + + + + The total number of entries to be saved or extracted. + + + + + The name of the last entry saved or extracted. + + + + + In an event handler, set this to cancel the save or extract + operation that is in progress. + + + + + The type of event being reported. + + + + + Returns the archive name associated to this event. + + + + + The number of bytes read or written so far for this entry. + + + + + Total number of bytes that will be read or written for this entry. + This number will be -1 if the value cannot be determined. + + + + + Provides information about the progress of a Read operation. + + + + + Provides information about the progress of a Add operation. + + + + + Provides information about the progress of a save operation. + + + + + Constructor for the SaveProgressEventArgs. + + the name of the zip archive. + whether this is before saving the entry, or after + The total number of entries in the zip archive. + Number of entries that have been saved. + The entry involved in the event. + + + + Number of entries saved so far. + + + + + Provides information about the progress of the extract operation. + + + + + Constructor for the ExtractProgressEventArgs. + + the name of the zip archive. + whether this is before saving the entry, or after + The total number of entries in the zip archive. + Number of entries that have been extracted. + The entry involved in the event. + The location to which entries are extracted. + + + + Number of entries extracted so far. This is set only if the + EventType is Extracting_BeforeExtractEntry or Extracting_AfterExtractEntry, and + the Extract() is occurring witin the scope of a call to ExtractAll(). + + + + + Returns the extraction target location, a filesystem path. + + + + + Provides information about the an error that occurred while zipping. + + + + + Returns the exception that occurred, if any. + + + + + Returns the name of the file that caused the exception, if any. + + + + + Issued when an ZipEntry.ExtractWithPassword() method is invoked + with an incorrect password. + + + + + Default ctor. + + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + The innerException for this exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The serialization info for the exception. + The streaming context from which to deserialize. + + + + Indicates that a read was attempted on a stream, and bad or incomplete data was + received. + + + + + Default ctor. + + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + The innerException for this exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The serialization info for the exception. + The streaming context from which to deserialize. + + + + Issued when an CRC check fails upon extracting an entry from a zip archive. + + + + + Default ctor. + + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The serialization info for the exception. + The streaming context from which to deserialize. + + + + Issued when errors occur saving a self-extracting archive. + + + + + Default ctor. + + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The serialization info for the exception. + The streaming context from which to deserialize. + + + + Indicates that an operation was attempted on a ZipFile which was not possible + given the state of the instance. For example, if you call Save() on a ZipFile + which has no filename set, you can get this exception. + + + + + Default ctor. + + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + The innerException for this exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The serialization info for the exception. + The streaming context from which to deserialize. + + + + Base class for all exceptions defined by and throw by the Zip library. + + + + + Default ctor. + + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + The innerException for this exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The serialization info for the exception. + The streaming context from which to deserialize. + + + + An enum for the options when extracting an entry would overwrite an existing file. + + + + + This enum describes the actions that the library can take when an + Extract() or ExtractWithPassword() method is called to extract an + entry to a filesystem, and the extraction would overwrite an existing filesystem + file. + + + + + + + Throw an exception when extraction would overwrite an existing file. (For + COM clients, this is a 0 (zero).) + + + + + When extraction would overwrite an existing file, overwrite the file silently. + The overwrite will happen even if the target file is marked as read-only. + (For COM clients, this is a 1.) + + + + + When extraction would overwrite an existing file, don't overwrite the file, silently. + (For COM clients, this is a 2.) + + + + + When extraction would overwrite an existing file, invoke the ExtractProgress + event, using an event type of . In + this way, the application can decide, just-in-time, whether to overwrite the + file. For example, a GUI application may wish to pop up a dialog to allow + the user to choose. You may want to examine the property before making + the decision. If, after your processing in the Extract progress event, you + want to NOT extract the file, set + on the ZipProgressEventArgs.CurrentEntry to DoNotOverwrite. + If you do want to extract the file, set ZipEntry.ExtractExistingFile + to OverwriteSilently. If you want to cancel the Extraction, set + ZipProgressEventArgs.Cancel to true. Cancelling differs from using + DoNotOverwrite in that a cancel will not extract any further entries, if + there are any. (For COM clients, the value of this enum is a 3.) + + + + + Collects general purpose utility methods. + + + + private null constructor + + + + Utility routine for transforming path names from filesystem format (on Windows that means backslashes) to + a format suitable for use within zipfiles. This means trimming the volume letter and colon (if any) And + swapping backslashes for forward slashes. + + source path. + transformed path + + + + Sanitize paths in zip files. This means making sure that relative paths in a zip file don't go outside + the top directory. Entries like something/../../../../Temp/evil.txt get sanitized to Temp/evil.txt + when extracting + + A path with forward slashes as directory separator + sanitized path + + + + Finds a signature in the zip stream. This is useful for finding + the end of a zip entry, for example, or the beginning of the next ZipEntry. + + + + + Scans through 64k at a time. + + + + If the method fails to find the requested signature, the stream Position + after completion of this method is unchanged. If the method succeeds in + finding the requested signature, the stream position after completion is + direct AFTER the signature found in the stream. + + + + The stream to search + The 4-byte signature to find + The number of bytes read + + + + Create a pseudo-random filename, suitable for use as a temporary + file, and open it. + + + + This method produces a filename of the form + DotNetZip-xxxxxxxx.tmp, where xxxxxxxx is replaced by randomly + chosen characters, and creates that file. + + + + + + Workitem 7889: handle ERROR_LOCK_VIOLATION during read + + + This could be gracefully handled with an extension attribute, but + This assembly used to be built for .NET 2.0, so could not use + extension methods. + + + + + A decorator stream. It wraps another stream, and performs bookkeeping + to keep track of the stream Position. + + + + In some cases, it is not possible to get the Position of a stream, let's + say, on a write-only output stream like ASP.NET's + Response.OutputStream, or on a different write-only stream + provided as the destination for the zip by the application. In this + case, programmers can use this counting stream to count the bytes read + or written. + + + Consider the scenario of an application that saves a self-extracting + archive (SFX), that uses a custom SFX stub. + + + Saving to a filesystem file, the application would open the + filesystem file (getting a FileStream), save the custom sfx stub + into it, and then call ZipFile.Save(), specifying the same + FileStream. ZipFile.Save() does the right thing for the zipentry + offsets, by inquiring the Position of the FileStream before writing + any data, and then adding that initial offset into any ZipEntry + offsets in the zip directory. Everything works fine. + + + Now suppose the application is an ASPNET application and it saves + directly to Response.OutputStream. It's not possible for DotNetZip to + inquire the Position, so the offsets for the SFX will be wrong. + + + The workaround is for the application to use this class to wrap + HttpResponse.OutputStream, then write the SFX stub and the ZipFile + into that wrapper stream. Because ZipFile.Save() can inquire the + Position, it will then do the right thing with the offsets. + + + + + + The constructor. + + The underlying stream + + + + Gets the wrapped stream. + + + + + The count of bytes written out to the stream. + + + + + the count of bytes that have been read from the stream. + + + + + Adjust the byte count on the stream. + + + + the number of bytes to subtract from the count. + + + + + Subtract delta from the count of bytes written to the stream. + This is necessary when seeking back, and writing additional data, + as happens in some cases when saving Zip files. + + + + + + The read method. + + The buffer to hold the data read from the stream. + the offset within the buffer to copy the first byte read. + the number of bytes to read. + the number of bytes read, after decryption and decompression. + + + + Write data into the stream. + + The buffer holding data to write to the stream. + the offset within that data array to find the first byte to write. + the number of bytes to write. + + + + Whether the stream can be read. + + + + + Whether it is possible to call Seek() on the stream. + + + + + Whether it is possible to call Write() on the stream. + + + + + Flushes the underlying stream. + + + + + The length of the underlying stream. + + + + + Returns the sum of number of bytes written, plus the initial + offset before writing. + + + + + The Position of the stream. + + + + + Seek in the stream. + + the offset point to seek to + the reference point from which to seek + The new position + + + + Set the length of the underlying stream. Be careful with this! + + + the length to set on the underlying stream. + + + + This is a helper class supporting WinZip AES encryption. + This class is intended for use only by the DotNetZip library. + + + + Most uses of the DotNetZip library will not involve direct calls into + the WinZipAesCrypto class. Instead, the WinZipAesCrypto class is + instantiated and used by the ZipEntry() class when WinZip AES + encryption or decryption on an entry is employed. + + + + + A stream that encrypts as it writes, or decrypts as it reads. The + Crypto is AES in CTR (counter) mode, which is compatible with the AES + encryption employed by WinZip 12.0. + + + + The AES/CTR encryption protocol used by WinZip works like this: + + - start with a counter, initialized to zero. + + - to encrypt, take the data by 16-byte blocks. For each block: + - apply the transform to the counter + - increement the counter + - XOR the result of the transform with the plaintext to + get the ciphertext. + - compute the mac on the encrypted bytes + - when finished with all blocks, store the computed MAC. + + - to decrypt, take the data by 16-byte blocks. For each block: + - compute the mac on the encrypted bytes, + - apply the transform to the counter + - increement the counter + - XOR the result of the transform with the ciphertext to + get the plaintext. + - when finished with all blocks, compare the computed MAC against + the stored MAC + + + + + + + The constructor. + + The underlying stream + To either encrypt or decrypt. + The pre-initialized WinZipAesCrypto object. + The maximum number of bytes to read from the stream. + + + + Returns the final HMAC-SHA1-80 for the data that was encrypted. + + + + + Close the stream. + + + + + Returns true if the stream can be read. + + + + + Always returns false. + + + + + Returns true if the CryptoMode is Encrypt. + + + + + Flush the content in the stream. + + + + + Getting this property throws a NotImplementedException. + + + + + Getting or Setting this property throws a NotImplementedException. + + + + + This method throws a NotImplementedException. + + + + + This method throws a NotImplementedException. + + + + + This class implements the "traditional" or "classic" PKZip encryption, + which today is considered to be weak. On the other hand it is + ubiquitous. This class is intended for use only by the DotNetZip + library. + + + + Most uses of the DotNetZip library will not involve direct calls into + the ZipCrypto class. Instead, the ZipCrypto class is instantiated and + used by the ZipEntry() class when encryption or decryption on an entry + is employed. If for some reason you really wanted to use a weak + encryption algorithm in some other application, you might use this + library. But you would be much better off using one of the built-in + strong encryption libraries in the .NET Framework, like the AES + algorithm or SHA. + + + + + The default constructor for ZipCrypto. + + + + This class is intended for internal use by the library only. It's + probably not useful to you. Seriously. Stop reading this + documentation. It's a waste of your time. Go do something else. + Check the football scores. Go get an ice cream with a friend. + Seriously. + + + + + + From AppNote.txt: + unsigned char decrypt_byte() + local unsigned short temp + temp :=- Key(2) | 2 + decrypt_byte := (temp * (temp ^ 1)) bitshift-right 8 + end decrypt_byte + + + + + Call this method on a cipher text to render the plaintext. You must + first initialize the cipher with a call to InitCipher. + + + + + var cipher = new ZipCrypto(); + cipher.InitCipher(Password); + // Decrypt the header. This has a side effect of "further initializing the + // encryption keys" in the traditional zip encryption. + byte[] DecryptedMessage = cipher.DecryptMessage(EncryptedMessage); + + + + The encrypted buffer. + + The number of bytes to encrypt. + Should be less than or equal to CipherText.Length. + + + The plaintext. + + + + This is the converse of DecryptMessage. It encrypts the plaintext + and produces a ciphertext. + + + The plain text buffer. + + + The number of bytes to encrypt. + Should be less than or equal to plainText.Length. + + + The ciphertext. + + + + This initializes the cipher with the given password. + See AppNote.txt for details. + + + + The passphrase for encrypting or decrypting with this cipher. + + + + + Step 1 - Initializing the encryption keys + ----------------------------------------- + Start with these keys: + Key(0) := 305419896 (0x12345678) + Key(1) := 591751049 (0x23456789) + Key(2) := 878082192 (0x34567890) + + Then, initialize the keys with a password: + + loop for i from 0 to length(password)-1 + update_keys(password(i)) + end loop + + Where update_keys() is defined as: + + update_keys(char): + Key(0) := crc32(key(0),char) + Key(1) := Key(1) + (Key(0) bitwiseAND 000000ffH) + Key(1) := Key(1) * 134775813 + 1 + Key(2) := crc32(key(2),key(1) rightshift 24) + end update_keys + + Where crc32(old_crc,char) is a routine that given a CRC value and a + character, returns an updated CRC value after applying the CRC-32 + algorithm described elsewhere in this document. + + + + + After the keys are initialized, then you can use the cipher to + encrypt the plaintext. + + + + Essentially we encrypt the password with the keys, then discard the + ciphertext for the password. This initializes the keys for later use. + + + + + + + A Stream for reading and concurrently decrypting data from a zip file, + or for writing and concurrently encrypting data to a zip file. + + + + The constructor. + The underlying stream + To either encrypt or decrypt. + The pre-initialized ZipCrypto object. + + + + Represents a single entry in a ZipFile. Typically, applications get a ZipEntry + by enumerating the entries within a ZipFile, or by adding an entry to a ZipFile. + + + + + True if the referenced entry is a directory. + + + + + Provides a human-readable string with information about the ZipEntry. + + + + + Reads one entry from the zip directory structure in the zip file. + + + + The zipfile for which a directory entry will be read. From this param, the + method gets the ReadStream and the expected text encoding + (ProvisionalAlternateEncoding) which is used if the entry is not marked + UTF-8. + + + + a list of previously seen entry names; used to prevent duplicates. + + + the entry read from the archive. + + + + Returns true if the passed-in value is a valid signature for a ZipDirEntry. + + the candidate 4-byte signature value. + true, if the signature is valid according to the PKWare spec. + + + + Default constructor. + + + Applications should never need to call this directly. It is exposed to + support COM Automation environments. + + + + + The time and date at which the file indicated by the ZipEntry was + last modified. + + + + + The DotNetZip library sets the LastModified value for an entry, equal to + the Last Modified time of the file in the filesystem. If an entry is + added from a stream, the library uses System.DateTime.Now for this + value, for the given entry. + + + + This property allows the application to retrieve and possibly set the + LastModified value on an entry, to an arbitrary value. values with a + setting of DateTimeKind.Unspecified are taken to be expressed as + DateTimeKind.Local. + + + + Be aware that because of the way PKWare's + Zip specification describes how times are stored in the zip file, + the full precision of the System.DateTime datatype is not stored + for the last modified time when saving zip files. For more information on + how times are formatted, see the PKZip specification. + + + + The actual last modified time of a file can be stored in multiple ways in + the zip file, and they are not mutually exclusive: + + + + + In the so-called "DOS" format, which has a 2-second precision. Values + are rounded to the nearest even second. For example, if the time on the + file is 12:34:43, then it will be stored as 12:34:44. This first value + is accessible via the LastModified property. This value is always + present in the metadata for each zip entry. In some cases the value is + invalid, or zero. + + + + In the so-called "Windows" or "NTFS" format, as an 8-byte integer + quantity expressed as the number of 1/10 milliseconds (in other words + the number of 100 nanosecond units) since January 1, 1601 (UTC). This + format is how Windows represents file times. This time is accessible + via the ModifiedTime property. + + + + In the "Unix" format, a 4-byte quantity specifying the number of seconds since + January 1, 1970 UTC. + + + + In an older format, now deprecated but still used by some current + tools. This format is also a 4-byte quantity specifying the number of + seconds since January 1, 1970 UTC. + + + + + + Zip tools and libraries will always at least handle (read or write) the + DOS time, and may also handle the other time formats. Keep in mind that + while the names refer to particular operating systems, there is nothing in + the time formats themselves that prevents their use on other operating + systems. + + + + When reading ZIP files, the DotNetZip library reads the Windows-formatted + time, if it is stored in the entry, and sets both LastModified and + ModifiedTime to that value. When writing ZIP files, the DotNetZip + library by default will write both time quantities. It can also emit the + Unix-formatted time if desired (See .) + + + + The last modified time of the file created upon a call to + ZipEntry.Extract() may be adjusted during extraction to compensate + for differences in how the .NET Base Class Library deals with daylight + saving time (DST) versus how the Windows filesystem deals with daylight + saving time. Raymond Chen provides + some good context. + + + + In a nutshell: Daylight savings time rules change regularly. In 2007, for + example, the inception week of DST changed. In 1977, DST was in place all + year round. In 1945, likewise. And so on. Win32 does not attempt to + guess which time zone rules were in effect at the time in question. It + will render a time as "standard time" and allow the app to change to DST + as necessary. .NET makes a different choice. + + + + Compare the output of FileInfo.LastWriteTime.ToString("f") with what you + see in the Windows Explorer property sheet for a file that was last + written to on the other side of the DST transition. For example, suppose + the file was last modified on October 17, 2003, during DST but DST is not + currently in effect. Explorer's file properties reports Thursday, October + 17, 2003, 8:45:38 AM, but .NETs FileInfo reports Thursday, October 17, + 2003, 9:45 AM. + + + + Win32 says, "Thursday, October 17, 2002 8:45:38 AM PST". Note: Pacific + STANDARD Time. Even though October 17 of that year occurred during Pacific + Daylight Time, Win32 displays the time as standard time because that's + what time it is NOW. + + + + .NET BCL assumes that the current DST rules were in place at the time in + question. So, .NET says, "Well, if the rules in effect now were also in + effect on October 17, 2003, then that would be daylight time" so it + displays "Thursday, October 17, 2003, 9:45 AM PDT" - daylight time. + + + + So .NET gives a value which is more intuitively correct, but is also + potentially incorrect, and which is not invertible. Win32 gives a value + which is intuitively incorrect, but is strictly correct. + + + + Because of this funkiness, this library adds one hour to the LastModified + time on the extracted file, if necessary. That is to say, if the time in + question had occurred in what the .NET Base Class Library assumed to be + DST. This assumption may be wrong given the constantly changing DST rules, + but it is the best we can do. + + + + + + + + Ability to set Last Modified DOS time to zero + (for using with EmitTimesInWindowsFormatWhenSaving+EmitTimesInUnixFormatWhenSaving setted to false) + some flasher hardware use as marker of first binary + + + + + Last Modified time for the file represented by the entry. + + + + + + This value corresponds to the "last modified" time in the NTFS file times + as described in the Zip + specification. When getting this property, the value may be + different from . When setting the property, + the property also gets set, but with a lower + precision. + + + + Let me explain. It's going to take a while, so get + comfortable. Originally, waaaaay back in 1989 when the ZIP specification + was originally described by the esteemed Mr. Phil Katz, the dominant + operating system of the time was MS-DOS. MSDOS stored file times with a + 2-second precision, because, c'mon, who is ever going to need better + resolution than THAT? And so ZIP files, regardless of the platform on + which the zip file was created, store file times in exactly the same format that DOS used + in 1989. + + + + Since then, the ZIP spec has evolved, but the internal format for file + timestamps remains the same. Despite the fact that the way times are + stored in a zip file is rooted in DOS heritage, any program on any + operating system can format a time in this way, and most zip tools and + libraries DO - they round file times to the nearest even second and store + it just like DOS did 25+ years ago. + + + + PKWare extended the ZIP specification to allow a zip file to store what + are called "NTFS Times" and "Unix(tm) times" for a file. These are the + last write, last access, and file creation + times of a particular file. These metadata are not actually specific + to NTFS or Unix. They are tracked for each file by NTFS and by various + Unix filesystems, but they are also tracked by other filesystems, too. + The key point is that the times are formatted in the zip file + in the same way that NTFS formats the time (ticks since win32 epoch), + or in the same way that Unix formats the time (seconds since Unix + epoch). As with the DOS time, any tool or library running on any + operating system is capable of formatting a time in one of these ways + and embedding it into the zip file. + + + + These extended times are higher precision quantities than the DOS time. + As described above, the (DOS) LastModified has a precision of 2 seconds. + The Unix time is stored with a precision of 1 second. The NTFS time is + stored with a precision of 0.0000001 seconds. The quantities are easily + convertible, except for the loss of precision you may incur. + + + + A zip archive can store the {C,A,M} times in NTFS format, in Unix format, + or not at all. Often a tool running on Unix or Mac will embed the times + in Unix format (1 second precision), while WinZip running on Windows might + embed the times in NTFS format (precision of of 0.0000001 seconds). When + reading a zip file with these "extended" times, in either format, + DotNetZip represents the values with the + ModifiedTime, AccessedTime and CreationTime + properties on the ZipEntry. + + + + While any zip application or library, regardless of the platform it + runs on, could use any of the time formats allowed by the ZIP + specification, not all zip tools or libraries do support all these + formats. Storing the higher-precision times for each entry is + optional for zip files, and many tools and libraries don't use the + higher precision quantities at all. The old DOS time, represented by + , is guaranteed to be present, though it + sometimes unset. + + + + Ok, getting back to the question about how the LastModified + property relates to this ModifiedTime + property... LastModified is always set, while + ModifiedTime is not. (The other times stored in the NTFS + times extension, CreationTime and AccessedTime also + may not be set on an entry that is read from an existing zip file.) + When reading a zip file, then LastModified takes the DOS time + that is stored with the file. If the DOS time has been stored as zero + in the zipfile, then this library will use DateTime.Now for the + LastModified value. If the ZIP file was created by an evolved + tool, then there will also be higher precision NTFS or Unix times in + the zip file. In that case, this library will read those times, and + set LastModified and ModifiedTime to the same value, the + one corresponding to the last write time of the file. If there are no + higher precision times stored for the entry, then ModifiedTime + remains unset (likewise AccessedTime and CreationTime), + and LastModified keeps its DOS time. + + + + When creating zip files with this library, by default the extended time + properties (ModifiedTime, AccessedTime, and + CreationTime) are set on the ZipEntry instance, and these data are + stored in the zip archive for each entry, in NTFS format. If you add an + entry from an actual filesystem file, then the entry gets the actual file + times for that file, to NTFS-level precision. If you add an entry from a + stream, or a string, then the times get the value DateTime.Now. In + this case LastModified and ModifiedTime will be identical, + to 2 seconds of precision. You can explicitly set the + CreationTime, AccessedTime, and ModifiedTime of an + entry using the property setters. If you want to set all of those + quantities, it's more efficient to use the method. Those + changes are not made permanent in the zip file until you call or one of its cousins. + + + + When creating a zip file, you can override the default behavior of + this library for formatting times in the zip file, disabling the + embedding of file times in NTFS format or enabling the storage of file + times in Unix format, or both. You may want to do this, for example, + when creating a zip file on Windows, that will be consumed on a Mac, + by an application that is not hip to the "NTFS times" format. To do + this, use the and + properties. A valid zip + file may store the file times in both formats. But, there are no + guarantees that a program running on Mac or Linux will gracefully + handle the NTFS-formatted times when Unix times are present, or that a + non-DotNetZip-powered application running on Windows will be able to + handle file times in Unix format. DotNetZip will always do something + reasonable; other libraries or tools may not. When in doubt, test. + + + + I'll bet you didn't think one person could type so much about time, eh? + And reading it was so enjoyable, too! Well, in appreciation, maybe you + should donate? + + + + + + + + + + + Last Access time for the file represented by the entry. + + + This value may or may not be meaningful. If the ZipEntry was read from an existing + Zip archive, this information may not be available. For an explanation of why, see + . + + + + + + + + The file creation time for the file represented by the entry. + + + + This value may or may not be meaningful. If the ZipEntry was read + from an existing zip archive, and the creation time was not set on the entry + when the zip file was created, then this property may be meaningless. For an + explanation of why, see . + + + + + + + + Sets the NTFS Creation, Access, and Modified times for the given entry. + + + + + When adding an entry from a file or directory, the Creation, Access, and + Modified times for the given entry are automatically set from the + filesystem values. When adding an entry from a stream or string, the + values are implicitly set to DateTime.Now. The application may wish to + set these values to some arbitrary value, before saving the archive, and + can do so using the various setters. If you want to set all of the times, + this method is more efficient. + + + + The values you set here will be retrievable with the , and properties. + + + + When this method is called, if both and are false, then the + EmitTimesInWindowsFormatWhenSaving flag is automatically set. + + + + DateTime values provided here without a DateTimeKind are assumed to be Local Time. + + + + the creation time of the entry. + the last access time of the entry. + the last modified time of the entry. + + + + + + + + + + Specifies whether the Creation, Access, and Modified times for the given + entry will be emitted in "Windows format" when the zip archive is saved. + + + + + An application creating a zip archive can use this flag to explicitly + specify that the file times for the entry should or should not be stored + in the zip archive in the format used by Windows. The default value of + this property is true. + + + + When adding an entry from a file or directory, the Creation (), Access (), and Modified + () times for the given entry are automatically + set from the filesystem values. When adding an entry from a stream or + string, all three values are implicitly set to DateTime.Now. Applications + can also explicitly set those times by calling . + + + + PKWARE's + zip specification describes multiple ways to format these times in a + zip file. One is the format Windows applications normally use: 100ns ticks + since Jan 1, 1601 UTC. The other is a format Unix applications typically + use: seconds since January 1, 1970 UTC. Each format can be stored in an + "extra field" in the zip entry when saving the zip archive. The former + uses an extra field with a Header Id of 0x000A, while the latter uses a + header ID of 0x5455. + + + + Not all zip tools and libraries can interpret these fields. Windows + compressed folders is one that can read the Windows Format timestamps, + while I believe the Infozip + tools can read the Unix format timestamps. Although the time values are + easily convertible, subject to a loss of precision, some tools and + libraries may be able to read only one or the other. DotNetZip can read or + write times in either or both formats. + + + + The times stored are taken from , , and . + + + + This property is not mutually exclusive from the property. It is + possible that a zip entry can embed the timestamps in both forms, one + form, or neither. But, there are no guarantees that a program running on + Mac or Linux will gracefully handle NTFS Formatted times, or that a + non-DotNetZip-powered application running on Windows will be able to + handle file times in Unix format. When in doubt, test. + + + + Normally you will use the ZipFile.EmitTimesInWindowsFormatWhenSaving + property, to specify the behavior for all entries in a zip, rather than + the property on each individual entry. + + + + + + + + + + + + + Specifies whether the Creation, Access, and Modified times for the given + entry will be emitted in "Unix(tm) format" when the zip archive is saved. + + + + + An application creating a zip archive can use this flag to explicitly + specify that the file times for the entry should or should not be stored + in the zip archive in the format used by Unix. By default this flag is + false, meaning the Unix-format times are not stored in the zip + archive. + + + + When adding an entry from a file or directory, the Creation (), Access (), and Modified + () times for the given entry are automatically + set from the filesystem values. When adding an entry from a stream or + string, all three values are implicitly set to DateTime.Now. Applications + can also explicitly set those times by calling . + + + + PKWARE's + zip specification describes multiple ways to format these times in a + zip file. One is the format Windows applications normally use: 100ns ticks + since Jan 1, 1601 UTC. The other is a format Unix applications typically + use: seconds since Jan 1, 1970 UTC. Each format can be stored in an + "extra field" in the zip entry when saving the zip archive. The former + uses an extra field with a Header Id of 0x000A, while the latter uses a + header ID of 0x5455. + + + + Not all tools and libraries can interpret these fields. Windows + compressed folders is one that can read the Windows Format timestamps, + while I believe the Infozip + tools can read the Unix format timestamps. Although the time values are + easily convertible, subject to a loss of precision, some tools and + libraries may be able to read only one or the other. DotNetZip can read or + write times in either or both formats. + + + + The times stored are taken from , , and . + + + + This property is not mutually exclusive from the property. It is + possible that a zip entry can embed the timestamps in both forms, one + form, or neither. But, there are no guarantees that a program running on + Mac or Linux will gracefully handle NTFS Formatted times, or that a + non-DotNetZip-powered application running on Windows will be able to + handle file times in Unix format. When in doubt, test. + + + + Normally you will use the ZipFile.EmitTimesInUnixFormatWhenSaving + property, to specify the behavior for all entries, rather than the + property on each individual entry. + + + + + + + + + + + + + The type of timestamp attached to the ZipEntry. + + + + This property is valid only for a ZipEntry that was read from a zip archive. + It indicates the type of timestamp attached to the entry. + + + + + + + + The file attributes for the entry. + + + + + + The attributes in NTFS include + ReadOnly, Archive, Hidden, System, and Indexed. When adding a + ZipEntry to a ZipFile, these attributes are set implicitly when + adding an entry from the filesystem. When adding an entry from a stream + or string, the Attributes are not set implicitly. Regardless of the way + an entry was added to a ZipFile, you can set the attributes + explicitly if you like. + + + + When reading a ZipEntry from a ZipFile, the attributes are + set according to the data stored in the ZipFile. If you extract the + entry from the archive to a filesystem file, DotNetZip will set the + attributes on the resulting file accordingly. + + + + The attributes can be set explicitly by the application. For example the + application may wish to set the FileAttributes.ReadOnly bit for all + entries added to an archive, so that on unpack, this attribute will be set + on the extracted file. Any changes you make to this property are made + permanent only when you call a Save() method on the ZipFile + instance that contains the ZipEntry. + + + + For example, an application may wish to zip up a directory and set the + ReadOnly bit on every file in the archive, so that upon later extraction, + the resulting files will be marked as ReadOnly. Not every extraction tool + respects these attributes, but if you unpack with DotNetZip, as for + example in a self-extracting archive, then the attributes will be set as + they are stored in the ZipFile. + + + + These attributes may not be interesting or useful if the resulting archive + is extracted on a non-Windows platform. How these attributes get used + upon extraction depends on the platform and tool used. + + + + + + + The name of the filesystem file, referred to by the ZipEntry. + + + + + This property specifies the thing-to-be-zipped on disk, and is set only + when the ZipEntry is being created from a filesystem file. If the + ZipFile is instantiated by reading an existing .zip archive, then + the LocalFileName will be null (Nothing in VB). + + + + When it is set, the value of this property may be different than , which is the path used in the archive itself. If you + call Zip.AddFile("foop.txt", AlternativeDirectory), then the path + used for the ZipEntry within the zip archive will be different + than this path. + + + + If the entry is being added from a stream, then this is null (Nothing in VB). + + + + + + + + The name of the file contained in the ZipEntry. + + + + + + This is the name of the entry in the ZipFile itself. When creating + a zip archive, if the ZipEntry has been created from a filesystem + file, via a call to or , or a related overload, the value + of this property is derived from the name of that file. The + FileName property does not include drive letters, and may include a + different directory path, depending on the value of the + directoryPathInArchive parameter used when adding the entry into + the ZipFile. + + + + In some cases there is no related filesystem file - for example when a + ZipEntry is created using or one of the similar overloads. In this case, the value of + this property is derived from the fileName and the directory path passed + to that method. + + + + When reading a zip file, this property takes the value of the entry name + as stored in the zip file. If you extract such an entry, the extracted + file will take the name given by this property. + + + + Applications can set this property when creating new zip archives or when + reading existing archives. When setting this property, the actual value + that is set will replace backslashes with forward slashes, in accordance + with the Zip + specification, for compatibility with Unix(tm) and ... get + this.... Amiga! + + + + If an application reads a ZipFile via or a related overload, and then explicitly + sets the FileName on an entry contained within the ZipFile, and + then calls , the application will effectively + rename the entry within the zip archive. + + + + If an application sets the value of FileName, then calls + Extract() on the entry, the entry is extracted to a file using the + newly set value as the filename. The FileName value is made + permanent in the zip archive only after a call to one of the + ZipFile.Save() methods on the ZipFile that contains the + ZipEntry. + + + + If an application attempts to set the FileName to a value that + would result in a duplicate entry in the ZipFile, an exception is + thrown. + + + + When a ZipEntry is contained within a ZipFile, applications + cannot rename the entry within the context of a foreach (For + Each in VB) loop, because of the way the ZipFile stores + entries. If you need to enumerate through all the entries and rename one + or more of them, use ZipFile.EntriesSorted as the + collection. See also, ZipFile.GetEnumerator(). + + + + + + + The stream that provides content for the ZipEntry. + + + + + + The application can use this property to set the input stream for an + entry on a just-in-time basis. Imagine a scenario where the application + creates a ZipFile comprised of content obtained from hundreds of + files, via calls to AddFile(). The DotNetZip library opens streams + on these files on a just-in-time basis, only when writing the entry out to + an external store within the scope of a ZipFile.Save() call. Only + one input stream is opened at a time, as each entry is being written out. + + + + Now imagine a different application that creates a ZipFile + with content obtained from hundreds of streams, added through . Normally the + application would supply an open stream to that call. But when large + numbers of streams are being added, this can mean many open streams at one + time, unnecessarily. + + + + To avoid this, call and specify delegates that open and close the stream at + the time of Save. + + + + + Setting the value of this property when the entry was not added from a + stream (for example, when the ZipEntry was added with or , or when the entry was added by + reading an existing zip archive) will throw an exception. + + + + + + + + A flag indicating whether the InputStream was provided Just-in-time. + + + + + + When creating a zip archive, an application can obtain content for one or + more of the ZipEntry instances from streams, using the method. At the time + of calling that method, the application can supply null as the value of + the stream parameter. By doing so, the application indicates to the + library that it will provide a stream for the entry on a just-in-time + basis, at the time one of the ZipFile.Save() methods is called and + the data for the various entries are being compressed and written out. + + + + In this case, the application can set the + property, typically within the SaveProgress event (event type: ) for that entry. + + + + The application will later want to call Close() and Dispose() on that + stream. In the SaveProgress event, when the event type is , the application can + do so. This flag indicates that the stream has been provided by the + application on a just-in-time basis and that it is the application's + responsibility to call Close/Dispose on that stream. + + + + + + + + An enum indicating the source of the ZipEntry. + + + + + The version of the zip engine needed to read the ZipEntry. + + + + + This is a readonly property, indicating the version of the Zip + specification that the extracting tool or library must support to + extract the given entry. Generally higher versions indicate newer + features. Older zip engines obviously won't know about new features, and + won't be able to extract entries that depend on those newer features. + + + + + value + Features + + + + 20 + a basic Zip Entry, potentially using PKZIP encryption. + + + + + 45 + The ZIP64 extension is used on the entry. + + + + + 46 + File is compressed using BZIP2 compression* + + + + 50 + File is encrypted using PkWare's DES, 3DES, (broken) RC2 or RC4 + + + + 51 + File is encrypted using PKWare's AES encryption or corrected RC2 encryption. + + + + 52 + File is encrypted using corrected RC2-64 encryption** + + + + 61 + File is encrypted using non-OAEP key wrapping*** + + + + 63 + File is compressed using LZMA, PPMd+, Blowfish, or Twofish + + + + + + There are other values possible, not listed here. DotNetZip supports + regular PKZip encryption, and ZIP64 extensions. DotNetZip cannot extract + entries that require a zip engine higher than 45. + + + + This value is set upon reading an existing zip file, or after saving a zip + archive. + + + + + + The comment attached to the ZipEntry. + + + + + Each entry in a zip file can optionally have a comment associated to + it. The comment might be displayed by a zip tool during extraction, for + example. + + + + By default, the Comment is encoded in IBM437 code page. You can + specify an alternative with and + . + + + + + + + + Indicates whether the entry requires ZIP64 extensions. + + + + + + This property is null (Nothing in VB) until a Save() method on the + containing instance has been called. The property is + non-null (HasValue is true) only after a Save() method has + been called. + + + + After the containing ZipFile has been saved, the Value of this + property is true if any of the following three conditions holds: the + uncompressed size of the entry is larger than 0xFFFFFFFF; the compressed + size of the entry is larger than 0xFFFFFFFF; the relative offset of the + entry within the zip archive is larger than 0xFFFFFFFF. These quantities + are not known until a Save() is attempted on the zip archive and + the compression is applied. + + + + If none of the three conditions holds, then the Value is false. + + + + A Value of false does not indicate that the entry, as saved in the + zip archive, does not use ZIP64. It merely indicates that ZIP64 is + not required. An entry may use ZIP64 even when not required if + the property on the containing + ZipFile instance is set to , or if + the property on the containing + ZipFile instance is set to + and the output stream was not seekable. + + + + + + + + Indicates whether the entry actually used ZIP64 extensions, as it was most + recently written to the output file or stream. + + + + + + This Nullable property is null (Nothing in VB) until a Save() + method on the containing instance has been + called. HasValue is true only after a Save() method has been + called. + + + + The value of this property for a particular ZipEntry may change + over successive calls to Save() methods on the containing ZipFile, + even if the file that corresponds to the ZipEntry does not. This + may happen if other entries contained in the ZipFile expand, + causing the offset for this particular entry to exceed 0xFFFFFFFF. + + + + + + + The bitfield for the entry as defined in the zip spec. You probably + never need to look at this. + + + + + You probably do not need to concern yourself with the contents of this + property, but in case you do: + + + + + bit + meaning + + + + 0 + set if encryption is used. + + + + 1-2 + + set to determine whether normal, max, fast deflation. DotNetZip library + always leaves these bits unset when writing (indicating "normal" + deflation"), but can read an entry with any value here. + + + + + 3 + + Indicates that the Crc32, Compressed and Uncompressed sizes are zero in the + local header. This bit gets set on an entry during writing a zip file, when + it is saved to a non-seekable output stream. + + + + + + 4 + reserved for "enhanced deflating". This library doesn't do enhanced deflating. + + + + 5 + set to indicate the zip is compressed patched data. This library doesn't do that. + + + + 6 + + set if PKWare's strong encryption is used (must also set bit 1 if bit 6 is + set). This bit is not set if WinZip's AES encryption is set. + + + + 7 + not used + + + + 8 + not used + + + + 9 + not used + + + + 10 + not used + + + + 11 + + Language encoding flag (EFS). If this bit is set, the filename and comment + fields for this file must be encoded using UTF-8. This library currently + does not support UTF-8. + + + + + 12 + Reserved by PKWARE for enhanced compression. + + + + 13 + + Used when encrypting the Central Directory to indicate selected data + values in the Local Header are masked to hide their actual values. See + the section in the Zip + specification describing the Strong Encryption Specification for + details. + + + + + 14 + Reserved by PKWARE. + + + + 15 + Reserved by PKWARE. + + + + + + + + + The compression method employed for this ZipEntry. + + + + + + The + Zip specification allows a variety of compression methods. This + library supports just two: 0x08 = Deflate. 0x00 = Store (no compression), + for reading or writing. + + + + When reading an entry from an existing zipfile, the value you retrieve + here indicates the compression method used on the entry by the original + creator of the zip. When writing a zipfile, you can specify either 0x08 + (Deflate) or 0x00 (None). If you try setting something else, you will get + an exception. + + + + You may wish to set CompressionMethod to CompressionMethod.None (0) + when zipping already-compressed data like a jpg, png, or mp3 file. + This can save time and cpu cycles. + + + + When setting this property on a ZipEntry that is read from an + existing zip file, calling ZipFile.Save() will cause the new + CompressionMethod to be used on the entry in the newly saved zip file. + + + + Setting this property may have the side effect of modifying the + CompressionLevel property. If you set the CompressionMethod to a + value other than None, and CompressionLevel is previously + set to None, then CompressionLevel will be set to + Default. + + + + + + + In this example, the first entry added to the zip archive uses the default + behavior - compression is used where it makes sense. The second entry, + the MP3 file, is added to the archive without being compressed. + + using (ZipFile zip = new ZipFile(ZipFileToCreate)) + { + ZipEntry e1= zip.AddFile(@"notes\Readme.txt"); + ZipEntry e2= zip.AddFile(@"music\StopThisTrain.mp3"); + e2.CompressionMethod = CompressionMethod.None; + zip.Save(); + } + + + + Using zip As New ZipFile(ZipFileToCreate) + zip.AddFile("notes\Readme.txt") + Dim e2 as ZipEntry = zip.AddFile("music\StopThisTrain.mp3") + e2.CompressionMethod = CompressionMethod.None + zip.Save + End Using + + + + + + Sets the compression level to be used for the entry when saving the zip + archive. This applies only for CompressionMethod = DEFLATE. + + + + + When using the DEFLATE compression method, Varying the compression + level used on entries can affect the size-vs-speed tradeoff when + compression and decompressing data streams or files. + + + + If you do not set this property, the default compression level is used, + which normally gives a good balance of compression efficiency and + compression speed. In some tests, using BestCompression can + double the time it takes to compress, while delivering just a small + increase in compression efficiency. This behavior will vary with the + type of data you compress. If you are in doubt, just leave this setting + alone, and accept the default. + + + + When setting this property on a ZipEntry that is read from an + existing zip file, calling ZipFile.Save() will cause the new + CompressionLevel to be used on the entry in the newly saved zip file. + + + + Setting this property may have the side effect of modifying the + CompressionMethod property. If you set the CompressionLevel + to a value other than None, CompressionMethod will be set + to Deflate, if it was previously None. + + + + Setting this property has no effect if the CompressionMethod is something + other than Deflate or None. + + + + + + + + The compressed size of the file, in bytes, within the zip archive. + + + + When reading a ZipFile, this value is read in from the existing + zip file. When creating or updating a ZipFile, the compressed + size is computed during compression. Therefore the value on a + ZipEntry is valid after a call to Save() (or one of its + overloads) in that case. + + + + + + + The size of the file, in bytes, before compression, or after extraction. + + + + When reading a ZipFile, this value is read in from the existing + zip file. When creating or updating a ZipFile, the uncompressed + size is computed during compression. Therefore the value on a + ZipEntry is valid after a call to Save() (or one of its + overloads) in that case. + + + + + + + The ratio of compressed size to uncompressed size of the ZipEntry. + + + + + This is a ratio of the compressed size to the uncompressed size of the + entry, expressed as a double in the range of 0 to 100+. A value of 100 + indicates no compression at all. It could be higher than 100 when the + compression algorithm actually inflates the data, as may occur for small + files, or uncompressible data that is encrypted. + + + + You could format it for presentation to a user via a format string of + "{3,5:F0}%" to see it as a percentage. + + + + If the size of the original uncompressed file is 0, implying a + denominator of 0, the return value will be zero. + + + + This property is valid after reading in an existing zip file, or after + saving the ZipFile that contains the ZipEntry. You cannot know the + effect of a compression transform until you try it. + + + + + + + The 32-bit CRC (Cyclic Redundancy Check) on the contents of the ZipEntry. + + + + + You probably don't need to concern yourself with this. It is used + internally by DotNetZip to verify files or streams upon extraction. + + The value is a 32-bit + CRC using 0xEDB88320 for the polynomial. This is the same CRC-32 used in + PNG, MPEG-2, and other protocols and formats. It is a read-only property; when + creating a Zip archive, the CRC for each entry is set only after a call to + Save() on the containing ZipFile. When reading an existing zip file, the value + of this property reflects the stored CRC for the entry. + + + + + + True if the entry is a directory (not a file). + This is a readonly property on the entry. + + + + + A derived property that is true if the entry uses encryption. + + + + + This is a readonly property on the entry. When reading a zip file, + the value for the ZipEntry is determined by the data read + from the zip file. After saving a ZipFile, the value of this + property for each ZipEntry indicates whether encryption was + actually used (which will have been true if the was set and the property + was something other than . + + + + + + Set this to specify which encryption algorithm to use for the entry when + saving it to a zip archive. + + + + + + Set this property in order to encrypt the entry when the ZipFile is + saved. When setting this property, you must also set a on the entry. If you set a value other than on this property and do not set a + Password then the entry will not be encrypted. The ZipEntry + data is encrypted as the ZipFile is saved, when you call or one of its cousins on the containing + ZipFile instance. You do not need to specify the Encryption + when extracting entries from an archive. + + + + The Zip specification from PKWare defines a set of encryption algorithms, + and the data formats for the zip archive that support them, and PKWare + supports those algorithms in the tools it produces. Other vendors of tools + and libraries, such as WinZip or Xceed, typically support a + subset of the algorithms specified by PKWare. These tools can + sometimes support additional different encryption algorithms and data + formats, not specified by PKWare. The AES Encryption specified and + supported by WinZip is the most popular example. This library supports a + subset of the complete set of algorithms specified by PKWare and other + vendors. + + + + There is no common, ubiquitous multi-vendor standard for strong encryption + within zip files. There is broad support for so-called "traditional" Zip + encryption, sometimes called Zip 2.0 encryption, as specified + by PKWare, but this encryption is considered weak and + breakable. This library currently supports the Zip 2.0 "weak" encryption, + and also a stronger WinZip-compatible AES encryption, using either 128-bit + or 256-bit key strength. If you want DotNetZip to support an algorithm + that is not currently supported, call the author of this library and maybe + we can talk business. + + + + The class also has a property. In most cases you will use + that property when setting encryption. This property takes + precedence over any Encryption set on the ZipFile itself. + Typically, you would use the per-entry Encryption when most entries in the + zip archive use one encryption algorithm, and a few entries use a + different one. If all entries in the zip file use the same Encryption, + then it is simpler to just set this property on the ZipFile itself, when + creating a zip archive. + + + + Some comments on updating archives: If you read a ZipFile, you can + modify the Encryption on an encrypted entry: you can remove encryption + from an entry that was encrypted; you can encrypt an entry that was not + encrypted previously; or, you can change the encryption algorithm. The + changes in encryption are not made permanent until you call Save() on the + ZipFile. To effect changes in encryption, the entry content is + streamed through several transformations, depending on the modification + the application has requested. For example if the entry is not encrypted + and the application sets Encryption to PkzipWeak, then at + the time of Save(), the original entry is read and decompressed, + then re-compressed and encrypted. Conversely, if the original entry is + encrypted with PkzipWeak encryption, and the application sets the + Encryption property to WinZipAes128, then at the time of + Save(), the original entry is decrypted via PKZIP encryption and + decompressed, then re-compressed and re-encrypted with AES. This all + happens automatically within the library, but it can be time-consuming for + large entries. + + + + Additionally, when updating archives, it is not possible to change the + password when changing the encryption algorithm. To change both the + algorithm and the password, you need to Save() the zipfile twice. First + set the Encryption to None, then call Save(). Then set the + Encryption to the new value (not "None"), then call Save() + once again. + + + + The WinZip AES encryption algorithms are not supported on the .NET Compact + Framework. + + + + + + This example creates a zip archive that uses encryption, and then extracts + entries from the archive. When creating the zip archive, the ReadMe.txt + file is zipped without using a password or encryption. The other file + uses encryption. + + + // Create a zip archive with AES Encryption. + using (ZipFile zip = new ZipFile()) + { + zip.AddFile("ReadMe.txt") + ZipEntry e1= zip.AddFile("2008-Regional-Sales-Report.pdf"); + e1.Encryption= EncryptionAlgorithm.WinZipAes256; + e1.Password= "Top.Secret.No.Peeking!"; + zip.Save("EncryptedArchive.zip"); + } + + // Extract a zip archive that uses AES Encryption. + // You do not need to specify the algorithm during extraction. + using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip")) + { + // Specify the password that is used during extraction, for + // all entries that require a password: + zip.Password= "Top.Secret.No.Peeking!"; + zip.ExtractAll("extractDirectory"); + } + + + + ' Create a zip that uses Encryption. + Using zip As New ZipFile() + zip.AddFile("ReadMe.txt") + Dim e1 as ZipEntry + e1= zip.AddFile("2008-Regional-Sales-Report.pdf") + e1.Encryption= EncryptionAlgorithm.WinZipAes256 + e1.Password= "Top.Secret.No.Peeking!" + zip.Save("EncryptedArchive.zip") + End Using + + ' Extract a zip archive that uses AES Encryption. + ' You do not need to specify the algorithm during extraction. + Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip")) + ' Specify the password that is used during extraction, for + ' all entries that require a password: + zip.Password= "Top.Secret.No.Peeking!" + zip.ExtractAll("extractDirectory") + End Using + + + + + + Thrown in the setter if EncryptionAlgorithm.Unsupported is specified. + + + ZipEntry.Password + ZipFile.Encryption + + + + The Password to be used when encrypting a ZipEntry upon + ZipFile.Save(), or when decrypting an entry upon Extract(). + + + + + This is a write-only property on the entry. Set this to request that the + entry be encrypted when writing the zip archive, or set it to specify the + password to be used when extracting an existing entry that is encrypted. + + + + The password set here is implicitly used to encrypt the entry during the + operation, or to decrypt during the or operation. If you set + the Password on a ZipEntry after calling Save(), there is no + effect. + + + + Consider setting the property when using a + password. Answering concerns that the standard password protection + supported by all zip tools is weak, WinZip has extended the ZIP + specification with a way to use AES Encryption to protect entries in the + Zip file. Unlike the "PKZIP 2.0" encryption specified in the PKZIP + specification, AES + Encryption uses a standard, strong, tested, encryption + algorithm. DotNetZip can create zip archives that use WinZip-compatible + AES encryption, if you set the property. But, + archives created that use AES encryption may not be readable by all other + tools and libraries. For example, Windows Explorer cannot read a + "compressed folder" (a zip file) that uses AES encryption, though it can + read a zip file that uses "PKZIP encryption." + + + + The class also has a + property. This property takes precedence over any password set on the + ZipFile itself. Typically, you would use the per-entry Password when most + entries in the zip archive use one password, and a few entries use a + different password. If all entries in the zip file use the same password, + then it is simpler to just set this property on the ZipFile itself, + whether creating a zip archive or extracting a zip archive. + + + + Some comments on updating archives: If you read a ZipFile, you + cannot modify the password on any encrypted entry, except by extracting + the entry with the original password (if any), removing the original entry + via , and then adding a new + entry with a new Password. + + + + For example, suppose you read a ZipFile, and there is an encrypted + entry. Setting the Password property on that ZipEntry and then + calling Save() on the ZipFile does not update the password + on that entry in the archive. Neither is an exception thrown. Instead, + what happens during the Save() is the existing entry is copied + through to the new zip archive, in its original encrypted form. Upon + re-reading that archive, the entry can be decrypted with its original + password. + + + + If you read a ZipFile, and there is an un-encrypted entry, you can set the + Password on the entry and then call Save() on the ZipFile, and get + encryption on that entry. + + + + + + + This example creates a zip file with two entries, and then extracts the + entries from the zip file. When creating the zip file, the two files are + added to the zip file using password protection. Each entry uses a + different password. During extraction, each file is extracted with the + appropriate password. + + + // create a file with encryption + using (ZipFile zip = new ZipFile()) + { + ZipEntry entry; + entry= zip.AddFile("Declaration.txt"); + entry.Password= "123456!"; + entry = zip.AddFile("Report.xls"); + entry.Password= "1Secret!"; + zip.Save("EncryptedArchive.zip"); + } + + // extract entries that use encryption + using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip")) + { + ZipEntry entry; + entry = zip["Declaration.txt"]; + entry.Password = "123456!"; + entry.Extract("extractDir"); + entry = zip["Report.xls"]; + entry.Password = "1Secret!"; + entry.Extract("extractDir"); + } + + + + + Using zip As New ZipFile + Dim entry as ZipEntry + entry= zip.AddFile("Declaration.txt") + entry.Password= "123456!" + entry = zip.AddFile("Report.xls") + entry.Password= "1Secret!" + zip.Save("EncryptedArchive.zip") + End Using + + + ' extract entries that use encryption + Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip")) + Dim entry as ZipEntry + entry = zip("Declaration.txt") + entry.Password = "123456!" + entry.Extract("extractDir") + entry = zip("Report.xls") + entry.Password = "1Secret!" + entry.Extract("extractDir") + End Using + + + + + + + ZipFile.Password + + + + The action the library should take when extracting a file that already exists. + + + + + This property affects the behavior of the Extract methods (one of the + Extract() or ExtractWithPassword() overloads), when + extraction would would overwrite an existing filesystem file. If you do + not set this property, the library throws an exception when extracting + an entry would overwrite an existing file. + + + + This property has no effect when extracting to a stream, or when the file to be + extracted does not already exist. + + + + + + + This example shows how to set the ExtractExistingFile property in + an ExtractProgress event, in response to user input. The + ExtractProgress event is invoked if and only if the + ExtractExistingFile property was previously set to + ExtractExistingFileAction.InvokeExtractProgressEvent. + + public static void ExtractProgress(object sender, ExtractProgressEventArgs e) + { + if (e.EventType == ZipProgressEventType.Extracting_BeforeExtractEntry) + Console.WriteLine("extract {0} ", e.CurrentEntry.FileName); + + else if (e.EventType == ZipProgressEventType.Extracting_ExtractEntryWouldOverwrite) + { + ZipEntry entry = e.CurrentEntry; + string response = null; + // Ask the user if he wants overwrite the file + do + { + Console.Write("Overwrite {0} in {1} ? (y/n/C) ", entry.FileName, e.ExtractLocation); + response = Console.ReadLine(); + Console.WriteLine(); + + } while (response != null && response[0]!='Y' && + response[0]!='N' && response[0]!='C'); + + if (response[0]=='C') + e.Cancel = true; + else if (response[0]=='Y') + entry.ExtractExistingFile = ExtractExistingFileAction.OverwriteSilently; + else + entry.ExtractExistingFile= ExtractExistingFileAction.DoNotOverwrite; + } + } + + + + + + The action to take when an error is encountered while + opening or reading files as they are saved into a zip archive. + + + + + Errors can occur within a call to ZipFile.Save, as the various files contained + in a ZipFile are being saved into the zip archive. During the + Save, DotNetZip will perform a File.Open on the file + associated to the ZipEntry, and then will read the entire contents of + the file as it is zipped. Either the open or the Read may fail, because + of lock conflicts or other reasons. Using this property, you can + specify the action to take when such errors occur. + + + + Typically you will NOT set this property on individual ZipEntry + instances. Instead, you will set the ZipFile.ZipErrorAction property on + the ZipFile instance, before adding any entries to the + ZipFile. If you do this, errors encountered on behalf of any of + the entries in the ZipFile will be handled the same way. + + + + But, if you use a handler, you will want + to set this property on the ZipEntry within the handler, to + communicate back to DotNetZip what you would like to do with the + particular error. + + + + + + + + + Indicates whether the entry was included in the most recent save. + + + An entry can be excluded or skipped from a save if there is an error + opening or reading the entry. + + + + + + A callback that allows the application to specify the compression to use + for a given entry that is about to be added to the zip archive. + + + + + See + + + + + + Set to indicate whether to use UTF-8 encoding for filenames and comments. + + + + + + If this flag is set, the comment and filename for the entry will be + encoded with UTF-8, as described in the Zip + specification, if necessary. "Necessary" means, the filename or + entry comment (if any) cannot be reflexively encoded and decoded using the + default code page, IBM437. + + + + Setting this flag to true is equivalent to setting to System.Text.Encoding.UTF8. + + + + This flag has no effect or relation to the text encoding used within the + file itself. + + + + + + + The text encoding to use for the FileName and Comment on this ZipEntry, + when the default encoding is insufficient. + + + + + + Don't use this property. See . + + + + + + + Specifies the alternate text encoding used by this ZipEntry + + + + The default text encoding used in Zip files for encoding filenames and + comments is IBM437, which is something like a superset of ASCII. In + cases where this is insufficient, applications can specify an + alternate encoding. + + + When creating a zip file, the usage of the alternate encoding is + governed by the property. + Typically you would set both properties to tell DotNetZip to employ an + encoding that is not IBM437 in the zipfile you are creating. + + + Keep in mind that because the ZIP specification states that the only + valid encodings to use are IBM437 and UTF-8, if you use something + other than that, then zip tools and libraries may not be able to + successfully read the zip archive you generate. + + + The zip specification states that applications should presume that + IBM437 is in use, except when a special bit is set, which indicates + UTF-8. There is no way to specify an arbitrary code page, within the + zip file itself. When you create a zip file encoded with gb2312 or + ibm861 or anything other than IBM437 or UTF-8, then the application + that reads the zip file needs to "know" which code page to use. In + some cases, the code page used when reading is chosen implicitly. For + example, WinRar uses the ambient code page for the host desktop + operating system. The pitfall here is that if you create a zip in + Copenhagen and send it to Tokyo, the reader of the zipfile may not be + able to decode successfully. + + + + This example shows how to create a zipfile encoded with a + language-specific encoding: + + using (var zip = new ZipFile()) + { + zip.AlternateEnoding = System.Text.Encoding.GetEncoding("ibm861"); + zip.AlternateEnodingUsage = ZipOption.Always; + zip.AddFileS(arrayOfFiles); + zip.Save("Myarchive-Encoded-in-IBM861.zip"); + } + + + + + + + Describes if and when this instance should apply + AlternateEncoding to encode the FileName and Comment, when + saving. + + + + + + Indicates whether an entry is marked as a text file. Be careful when + using on this property. Unless you have a good reason, you should + probably ignore this property. + + + + + The ZIP format includes a provision for specifying whether an entry in + the zip archive is a text or binary file. This property exposes that + metadata item. Be careful when using this property: It's not clear + that this property as a firm meaning, across tools and libraries. + + + + To be clear, when reading a zip file, the property value may or may + not be set, and its value may or may not be valid. Not all entries + that you may think of as "text" entries will be so marked, and entries + marked as "text" are not guaranteed in any way to be text entries. + Whether the value is set and set correctly depends entirely on the + application that produced the zip file. + + + + There are many zip tools available, and when creating zip files, some + of them "respect" the IsText metadata field, and some of them do not. + Unfortunately, even when an application tries to do "the right thing", + it's not always clear what "the right thing" is. + + + + There's no firm definition of just what it means to be "a text file", + and the zip specification does not help in this regard. Twenty years + ago, text was ASCII, each byte was less than 127. IsText meant, all + bytes in the file were less than 127. These days, it is not the case + that all text files have all bytes less than 127. Any unicode file + may have bytes that are above 0x7f. The zip specification has nothing + to say on this topic. Therefore, it's not clear what IsText really + means. + + + + This property merely tells a reading application what is stored in the + metadata for an entry, without guaranteeing its validity or its + meaning. + + + + When DotNetZip is used to create a zipfile, it attempts to set this + field "correctly." For example, if a file ends in ".txt", this field + will be set. Your application may override that default setting. When + writing a zip file, you must set the property before calling + Save() on the ZipFile. + + + + When reading a zip file, a more general way to decide just what kind + of file is contained in a particular entry is to use the file type + database stored in the operating system. The operating system stores + a table that says, a file with .jpg extension is a JPG image file, a + file with a .xml extension is an XML document, a file with a .txt is a + pure ASCII text document, and so on. To get this information on + Windows, you + need to read and parse the registry. + + + + + using (var zip = new ZipFile()) + { + var e = zip.UpdateFile("Descriptions.mme", ""); + e.IsText = true; + zip.Save(zipPath); + } + + + + Using zip As New ZipFile + Dim e2 as ZipEntry = zip.AddFile("Descriptions.mme", "") + e.IsText= True + zip.Save(zipPath) + End Using + + + + + Provides a string representation of the instance. + a string representation of the instance. + + + + Extract the entry to the filesystem, starting at the current + working directory. + + + + This method has a bunch of overloads! One of them is sure to + be the right one for you... If you don't like these, check + out the ExtractWithPassword() methods. + + + + + + + + + This method extracts an entry from a zip file into the current + working directory. The path of the entry as extracted is the full + path as specified in the zip archive, relative to the current + working directory. After the file is extracted successfully, the + file attributes and timestamps are set. + + + + The action taken when extraction an entry would overwrite an + existing file is determined by the property. + + + + Within the call to Extract(), the content for the entry is + written into a filesystem file, and then the last modified time of the + file is set according to the property on + the entry. See the remarks the property for + some details about the last modified time. + + + + + + + Extract the entry to a file in the filesystem, using the specified + behavior when extraction would overwrite an existing file. + + + + + See the remarks on the property, for some + details about how the last modified time of the file is set after + extraction. + + + + + The action to take if extraction would overwrite an existing file. + + + + + Extracts the entry to the specified stream. + + + + + The caller can specify any write-able stream, for example a , a , or ASP.NET's + Response.OutputStream. The content will be decrypted and + decompressed as necessary. If the entry is encrypted and no password + is provided, this method will throw. + + + The position on the stream is not reset by this method before it extracts. + You may want to call stream.Seek() before calling ZipEntry.Extract(). + + + + + the stream to which the entry should be extracted. + + + + + + Extract the entry to the filesystem, starting at the specified base + directory. + + + the pathname of the base directory + + + + + + This example extracts only the entries in a zip file that are .txt files, + into a directory called "textfiles". + + using (ZipFile zip = ZipFile.Read("PackedDocuments.zip")) + { + foreach (string s1 in zip.EntryFilenames) + { + if (s1.EndsWith(".txt")) + { + zip[s1].Extract("textfiles"); + } + } + } + + + Using zip As ZipFile = ZipFile.Read("PackedDocuments.zip") + Dim s1 As String + For Each s1 In zip.EntryFilenames + If s1.EndsWith(".txt") Then + zip(s1).Extract("textfiles") + End If + Next + End Using + + + + + + + Using this method, existing entries in the filesystem will not be + overwritten. If you would like to force the overwrite of existing + files, see the property, or call + . + + + + See the remarks on the property, for some + details about how the last modified time of the created file is set. + + + + + + Extract the entry to the filesystem, starting at the specified base + directory, and using the specified behavior when extraction would + overwrite an existing file. + + + + + See the remarks on the property, for some + details about how the last modified time of the created file is set. + + + + + + String sZipPath = "Airborne.zip"; + String sFilePath = "Readme.txt"; + String sRootFolder = "Digado"; + using (ZipFile zip = ZipFile.Read(sZipPath)) + { + if (zip.EntryFileNames.Contains(sFilePath)) + { + // use the string indexer on the zip file + zip[sFileName].Extract(sRootFolder, + ExtractExistingFileAction.OverwriteSilently); + } + } + + + + Dim sZipPath as String = "Airborne.zip" + Dim sFilePath As String = "Readme.txt" + Dim sRootFolder As String = "Digado" + Using zip As ZipFile = ZipFile.Read(sZipPath) + If zip.EntryFileNames.Contains(sFilePath) + ' use the string indexer on the zip file + zip(sFilePath).Extract(sRootFolder, _ + ExtractExistingFileAction.OverwriteSilently) + End If + End Using + + + + the pathname of the base directory + + The action to take if extraction would overwrite an existing file. + + + + + Extract the entry to the filesystem, using the current working directory + and the specified password. + + + + This method has a bunch of overloads! One of them is sure to be + the right one for you... + + + + + + + + + Existing entries in the filesystem will not be overwritten. If you + would like to force the overwrite of existing files, see the property, or call + . + + + + See the remarks on the property for some + details about how the "last modified" time of the created file is + set. + + + + + In this example, entries that use encryption are extracted using a + particular password. + + using (var zip = ZipFile.Read(FilePath)) + { + foreach (ZipEntry e in zip) + { + if (e.UsesEncryption) + e.ExtractWithPassword("Secret!"); + else + e.Extract(); + } + } + + + Using zip As ZipFile = ZipFile.Read(FilePath) + Dim e As ZipEntry + For Each e In zip + If (e.UsesEncryption) + e.ExtractWithPassword("Secret!") + Else + e.Extract + End If + Next + End Using + + + The Password to use for decrypting the entry. + + + + Extract the entry to the filesystem, starting at the specified base + directory, and using the specified password. + + + + + + + + Existing entries in the filesystem will not be overwritten. If you + would like to force the overwrite of existing files, see the property, or call + . + + + + See the remarks on the property, for some + details about how the last modified time of the created file is set. + + + + The pathname of the base directory. + The Password to use for decrypting the entry. + + + + Extract the entry to a file in the filesystem, relative to the + current directory, using the specified behavior when extraction + would overwrite an existing file. + + + + + See the remarks on the property, for some + details about how the last modified time of the created file is set. + + + + The Password to use for decrypting the entry. + + + The action to take if extraction would overwrite an existing file. + + + + + Extract the entry to the filesystem, starting at the specified base + directory, and using the specified behavior when extraction would + overwrite an existing file. + + + + See the remarks on the property, for some + details about how the last modified time of the created file is set. + + + the pathname of the base directory + + The action to take if extraction would + overwrite an existing file. + + The Password to use for decrypting the entry. + + + + Extracts the entry to the specified stream, using the specified + Password. For example, the caller could extract to Console.Out, or + to a MemoryStream. + + + + + The caller can specify any write-able stream, for example a , a , or ASP.NET's + Response.OutputStream. The content will be decrypted and + decompressed as necessary. If the entry is encrypted and no password + is provided, this method will throw. + + + The position on the stream is not reset by this method before it extracts. + You may want to call stream.Seek() before calling ZipEntry.Extract(). + + + + + + the stream to which the entry should be extracted. + + + The password to use for decrypting the entry. + + + + + Opens a readable stream corresponding to the zip entry in the + archive. The stream decompresses and decrypts as necessary, as it + is read. + + + + + + DotNetZip offers a variety of ways to extract entries from a zip + file. This method allows an application to extract an entry by + reading a . + + + + The return value is of type . Use it as you would any + stream for reading. When an application calls on that stream, it will + receive data from the zip entry that is decrypted and decompressed + as necessary. + + + + CrcCalculatorStream adds one additional feature: it keeps a + CRC32 checksum on the bytes of the stream as it is read. The CRC + value is available in the property on the + CrcCalculatorStream. When the read is complete, your + application + should check this CRC against the + property on the ZipEntry to validate the content of the + ZipEntry. You don't have to validate the entry using the CRC, but + you should, to verify integrity. Check the example for how to do + this. + + + + If the entry is protected with a password, then you need to provide + a password prior to calling , either by + setting the property on the entry, or the + property on the ZipFile + itself. Or, you can use , the + overload of OpenReader that accepts a password parameter. + + + + If you want to extract entry data into a write-able stream that is + already opened, like a , do not + use this method. Instead, use . + + + + Your application may use only one stream created by OpenReader() at + a time, and you should not call other Extract methods before + completing your reads on a stream obtained from OpenReader(). This + is because there is really only one source stream for the compressed + content. A call to OpenReader() seeks in the source stream, to the + beginning of the compressed content. A subsequent call to + OpenReader() on a different entry will seek to a different position + in the source stream, as will a call to Extract() or one of its + overloads. This will corrupt the state for the decompressing stream + from the original call to OpenReader(). + + + + The OpenReader() method works only when the ZipEntry is + obtained from an instance of ZipFile. This method will throw + an exception if the ZipEntry is obtained from a . + + + + + This example shows how to open a zip archive, then read in a named + entry via a stream. After the read loop is complete, the code + compares the calculated during the read loop with the expected CRC + on the ZipEntry, to verify the extraction. + + using (ZipFile zip = new ZipFile(ZipFileToRead)) + { + ZipEntry e1= zip["Elevation.mp3"]; + using (Ionic.Zlib.CrcCalculatorStream s = e1.OpenReader()) + { + byte[] buffer = new byte[4096]; + int n, totalBytesRead= 0; + do { + n = s.Read(buffer,0, buffer.Length); + totalBytesRead+=n; + } while (n>0); + if (s.Crc32 != e1.Crc32) + throw new Exception(string.Format("The Zip Entry failed the CRC Check. (0x{0:X8}!=0x{1:X8})", s.Crc32, e1.Crc32)); + if (totalBytesRead != e1.UncompressedSize) + throw new Exception(string.Format("We read an unexpected number of bytes. ({0}!={1})", totalBytesRead, e1.UncompressedSize)); + } + } + + + Using zip As New ZipFile(ZipFileToRead) + Dim e1 As ZipEntry = zip.Item("Elevation.mp3") + Using s As Ionic.Zlib.CrcCalculatorStream = e1.OpenReader + Dim n As Integer + Dim buffer As Byte() = New Byte(4096) {} + Dim totalBytesRead As Integer = 0 + Do + n = s.Read(buffer, 0, buffer.Length) + totalBytesRead = (totalBytesRead + n) + Loop While (n > 0) + If (s.Crc32 <> e1.Crc32) Then + Throw New Exception(String.Format("The Zip Entry failed the CRC Check. (0x{0:X8}!=0x{1:X8})", s.Crc32, e1.Crc32)) + End If + If (totalBytesRead <> e1.UncompressedSize) Then + Throw New Exception(String.Format("We read an unexpected number of bytes. ({0}!={1})", totalBytesRead, e1.UncompressedSize)) + End If + End Using + End Using + + + + The Stream for reading. + + + + Opens a readable stream for an encrypted zip entry in the archive. + The stream decompresses and decrypts as necessary, as it is read. + + + + + See the documentation on the method for + full details. This overload allows the application to specify a + password for the ZipEntry to be read. + + + + The password to use for decrypting the entry. + The Stream for reading. + + + + Pass in either basedir or s, but not both. + In other words, you can extract to a stream or to a directory (filesystem), but not both! + The Password param is required for encrypted entries. + + + + + Extract to a stream + In other words, you can extract to a stream or to a directory (filesystem), but not both! + The Password param is required for encrypted entries. + + + + + Validates that the args are consistent; returning whether the caller can return + because it's done, or not (caller should continue) + + + + + Validates that the args are consistent; returning whether the caller can return + because it's done, or not (caller should continue) + + + + + Reads one ZipEntry from the given stream. The content for + the entry does not get decompressed or decrypted. This method + basically reads metadata, and seeks. + + the ZipContainer this entry belongs to. + + true of this is the first entry being read from the stream. + + the ZipEntry read from the stream. + + + + Finds a particular segment in the given extra field. + This is used when modifying a previously-generated + extra field, in particular when removing the AES crypto + segment in the extra field. + + + + + At current cursor position in the stream, read the extra + field, and set the properties on the ZipEntry instance + appropriately. This can be called when processing the + Extra field in the Central Directory, or in the local + header. + + + + + generate and return a byte array that encodes the filename + for the entry. + + + + side effects: generate and store into _CommentBytes the + byte array for any comment attached to the entry. Also + sets _actualEncoding to indicate the actual encoding + used. The same encoding is used for both filename and + comment. + + + + + + Stores the position of the entry source stream, or, if the position is + already stored, seeks to that position. + + + + + This method is called in prep for reading the source stream. If PKZIP + encryption is used, then we need to calc the CRC32 before doing the + encryption, because the CRC is used in the 12th byte of the PKZIP + encryption header. So, we need to be able to seek backward in the source + when saving the ZipEntry. This method is called from the place that + calculates the CRC, and also from the method that does the encryption of + the file data. + + + + The first time through, this method sets the _sourceStreamOriginalPosition + field. Subsequent calls to this method seek to that position. + + + + + + Copy metadata that may have been changed by the app. We do this when + resetting the zipFile instance. If the app calls Save() on a ZipFile, then + tries to party on that file some more, we may need to Reset() it , which + means re-reading the entries and then copying the metadata. I think. + + + + + Set the input stream and get its length, if possible. The length is + used for progress updates, AND, to allow an optimization in case of + a stream/file of zero length. In that case we skip the Encrypt and + compression Stream. (like DeflateStream or BZip2OutputStream) + + + + + Prepare the given stream for output - wrap it in a CountingStream, and + then in a CRC stream, and an encryptor and deflator as appropriate. + + + + Previously this was used in ZipEntry.Write(), but in an effort to + introduce some efficiencies in that method I've refactored to put the + code inline. This method still gets called by ZipOutputStream. + + + + + + An enum that specifies the type of timestamp available on the ZipEntry. + + + + + + The last modified time of a file can be stored in multiple ways in + a zip file, and they are not mutually exclusive: + + + + + In the so-called "DOS" format, which has a 2-second precision. Values + are rounded to the nearest even second. For example, if the time on the + file is 12:34:43, then it will be stored as 12:34:44. This first value + is accessible via the LastModified property. This value is always + present in the metadata for each zip entry. In some cases the value is + invalid, or zero. + + + + In the so-called "Windows" or "NTFS" format, as an 8-byte integer + quantity expressed as the number of 1/10 milliseconds (in other words + the number of 100 nanosecond units) since January 1, 1601 (UTC). This + format is how Windows represents file times. This time is accessible + via the ModifiedTime property. + + + + In the "Unix" format, a 4-byte quantity specifying the number of seconds since + January 1, 1970 UTC. + + + + In an older format, now deprecated but still used by some current + tools. This format is also a 4-byte quantity specifying the number of + seconds since January 1, 1970 UTC. + + + + + + This bit field describes which of the formats were found in a ZipEntry that was read. + + + + + + + Default value. + + + + + A DOS timestamp with 2-second precision. + + + + + A Windows timestamp with 100-ns precision. + + + + + A Unix timestamp with 1-second precision. + + + + + A Unix timestamp with 1-second precision, stored in InfoZip v1 format. This + format is outdated and is supported for reading archives only. + + + + + The method of compression to use for a particular ZipEntry. + + + + PKWare's + ZIP Specification describes a number of distinct + cmopression methods that can be used within a zip + file. DotNetZip supports a subset of them. + + + + + No compression at all. For COM environments, the value is 0 (zero). + + + + + DEFLATE compression, as described in IETF RFC + 1951. This is the "normal" compression used in zip + files. For COM environments, the value is 8. + + + + + BZip2 compression, a compression algorithm developed by Julian Seward. + For COM environments, the value is 12. + + + + + An enum that specifies the source of the ZipEntry. + + + + + Default value. Invalid on a bonafide ZipEntry. + + + + + The entry was instantiated by calling AddFile() or another method that + added an entry from the filesystem. + + + + + The entry was instantiated via or + . + + + + + The ZipEntry was instantiated by reading a zipfile. + + + + + The content for the ZipEntry will be or was provided by the WriteDelegate. + + + + + The content for the ZipEntry will be obtained from the stream dispensed by the OpenDelegate. + The entry was instantiated via . + + + + + The content for the ZipEntry will be or was obtained from a ZipOutputStream. + + + + + An enum providing the options when an error occurs during opening or reading + of a file or directory that is being saved to a zip file. + + + + + This enum describes the actions that the library can take when an error occurs + opening or reading a file, as it is being saved into a Zip archive. + + + + In some cases an error will occur when DotNetZip tries to open a file to be + added to the zip archive. In other cases, an error might occur after the + file has been successfully opened, while DotNetZip is reading the file. + + + + The first problem might occur when calling AddDirectory() on a directory + that contains a Clipper .dbf file; the file is locked by Clipper and + cannot be opened by another process. An example of the second problem is + the ERROR_LOCK_VIOLATION that results when a file is opened by another + process, but not locked, and a range lock has been taken on the file. + Microsoft Outlook takes range locks on .PST files. + + + + + + Throw an exception when an error occurs while zipping. This is the default + behavior. (For COM clients, this is a 0 (zero).) + + + + + When an error occurs during zipping, for example a file cannot be opened, + skip the file causing the error, and continue zipping. (For COM clients, + this is a 1.) + + + + + When an error occurs during zipping, for example a file cannot be opened, + retry the operation that caused the error. Be careful with this option. If + the error is not temporary, the library will retry forever. (For COM + clients, this is a 2.) + + + + + When an error occurs, invoke the zipError event. The event type used is + . A typical use of this option: + a GUI application may wish to pop up a dialog to allow the user to view the + error that occurred, and choose an appropriate action. After your + processing in the error event, if you want to skip the file, set on the + ZipProgressEventArgs.CurrentEntry to Skip. If you want the + exception to be thrown, set ZipErrorAction on the CurrentEntry + to Throw. If you want to cancel the zip, set + ZipProgressEventArgs.Cancel to true. Cancelling differs from using + Skip in that a cancel will not save any further entries, if there are any. + (For COM clients, the value of this enum is a 3.) + + + + + Options for using ZIP64 extensions when saving zip archives. + + + + + + Designed many years ago, the original zip + specification from PKWARE allowed for 32-bit quantities for the + compressed and uncompressed sizes of zip entries, as well as a 32-bit quantity + for specifying the length of the zip archive itself, and a maximum of 65535 + entries. These limits are now regularly exceeded in many backup and archival + scenarios. Recently, PKWare added extensions to the original zip spec, called + "ZIP64 extensions", to raise those limitations. This property governs whether + DotNetZip will use those extensions when writing zip archives. The use of + these extensions is optional and explicit in DotNetZip because, despite the + status of ZIP64 as a bona fide standard, many other zip tools and libraries do + not support ZIP64, and therefore a zip file with ZIP64 extensions may be + unreadable by some of those other tools. + + + + Set this property to to always use ZIP64 + extensions when saving, regardless of whether your zip archive needs it. + Suppose you add 5 files, each under 100k, to a ZipFile. If you specify Always + for this flag, you will get a ZIP64 archive, though the archive does not need + to use ZIP64 because none of the original zip limits had been exceeded. + + + + Set this property to to tell the DotNetZip + library to never use ZIP64 extensions. This is useful for maximum + compatibility and interoperability, at the expense of the capability of + handling large files or large archives. NB: Windows Explorer in Windows XP + and Windows Vista cannot currently extract files from a zip64 archive, so if + you want to guarantee that a zip archive produced by this library will work in + Windows Explorer, use Never. If you set this property to , and your application creates a zip that would + exceed one of the Zip limits, the library will throw an exception while saving + the zip file. + + + + Set this property to to tell the + DotNetZip library to use the ZIP64 extensions when required by the + entry. After the file is compressed, the original and compressed sizes are + checked, and if they exceed the limits described above, then zip64 can be + used. That is the general idea, but there is an additional wrinkle when saving + to a non-seekable device, like the ASP.NET Response.OutputStream, or + Console.Out. When using non-seekable streams for output, the entry + header - which indicates whether zip64 is in use - is emitted before it is + known if zip64 is necessary. It is only after all entries have been saved + that it can be known if ZIP64 will be required. On seekable output streams, + after saving all entries, the library can seek backward and re-emit the zip + file header to be consistent with the actual ZIP64 requirement. But using a + non-seekable output stream, the library cannot seek backward, so the header + can never be changed. In other words, the archive's use of ZIP64 extensions is + not alterable after the header is emitted. Therefore, when saving to + non-seekable streams, using is the same + as using : it will always produce a zip + archive that uses ZIP64 extensions. + + + + + + + The default behavior, which is "Never". + (For COM clients, this is a 0 (zero).) + + + + + Do not use ZIP64 extensions when writing zip archives. + (For COM clients, this is a 0 (zero).) + + + + + Use ZIP64 extensions when writing zip archives, as necessary. + For example, when a single entry exceeds 0xFFFFFFFF in size, or when the archive as a whole + exceeds 0xFFFFFFFF in size, or when there are more than 65535 entries in an archive. + (For COM clients, this is a 1.) + + + + + Always use ZIP64 extensions when writing zip archives, even when unnecessary. + (For COM clients, this is a 2.) + + + + + An enum representing the values on a three-way toggle switch + for various options in the library. This might be used to + specify whether to employ a particular text encoding, or to use + ZIP64 extensions, or some other option. + + + + + The default behavior. This is the same as "Never". + (For COM clients, this is a 0 (zero).) + + + + + Never use the associated option. + (For COM clients, this is a 0 (zero).) + + + + + Use the associated behavior "as necessary." + (For COM clients, this is a 1.) + + + + + Use the associated behavior Always, whether necessary or not. + (For COM clients, this is a 2.) + + + + + A class for collecting the various options that can be used when + Reading zip files for extraction or update. + + + + + When reading a zip file, there are several options an + application can set, to modify how the file is read, or what + the library does while reading. This class collects those + options into one container. + + + + Pass an instance of the ReadOptions class into the + ZipFile.Read() method. + + + . + . + + + + + An event handler for Read operations. When opening large zip + archives, you may want to display a progress bar or other + indicator of status progress while reading. This parameter + allows you to specify a ReadProgress Event Handler directly. + When you call Read(), the progress event is invoked as + necessary. + + + + + The System.IO.TextWriter to use for writing verbose status messages + during operations on the zip archive. A console application may wish to + pass System.Console.Out to get messages on the Console. A graphical + or headless application may wish to capture the messages in a different + TextWriter, such as a System.IO.StringWriter. + + + + + The System.Text.Encoding to use when reading in the zip archive. Be + careful specifying the encoding. If the value you use here is not the same + as the Encoding used when the zip archive was created (possibly by a + different archiver) you will get unexpected results and possibly exceptions. + + + + + + + + Provides a stream metaphor for reading zip files. + + + + + This class provides an alternative programming model for reading zip files to + the one enabled by the class. Use this when reading zip + files, as an alternative to the class, when you would + like to use a Stream class to read the file. + + + + Some application designs require a readable stream for input. This stream can + be used to read a zip file, and extract entries. + + + + Both the ZipInputStream class and the ZipFile class can be used + to read and extract zip files. Both of them support many of the common zip + features, including Unicode, different compression levels, and ZIP64. The + programming models differ. For example, when extracting entries via calls to + the GetNextEntry() and Read() methods on the + ZipInputStream class, the caller is responsible for creating the file, + writing the bytes into the file, setting the attributes on the file, and + setting the created, last modified, and last accessed timestamps on the + file. All of these things are done automatically by a call to ZipEntry.Extract(). For this reason, the + ZipInputStream is generally recommended for when your application wants + to extract the data, without storing that data into a file. + + + + Aside from the obvious differences in programming model, there are some + differences in capability between the ZipFile class and the + ZipInputStream class. + + + + + ZipFile can be used to create or update zip files, or read and + extract zip files. ZipInputStream can be used only to read and + extract zip files. If you want to use a stream to create zip files, check + out the . + + + + ZipInputStream cannot read segmented or spanned + zip files. + + + + ZipInputStream will not read Zip file comments. + + + + When reading larger files, ZipInputStream will always underperform + ZipFile. This is because the ZipInputStream does a full scan on the + zip file, while the ZipFile class reads the central directory of the + zip file. + + + + + + + + + Create a ZipInputStream, wrapping it around an existing stream. + + + + + + While the class is generally easier + to use, this class provides an alternative to those + applications that want to read from a zipfile directly, + using a . + + + + Both the ZipInputStream class and the ZipFile class can be used + to read and extract zip files. Both of them support many of the common zip + features, including Unicode, different compression levels, and ZIP64. The + programming models differ. For example, when extracting entries via calls to + the GetNextEntry() and Read() methods on the + ZipInputStream class, the caller is responsible for creating the file, + writing the bytes into the file, setting the attributes on the file, and + setting the created, last modified, and last accessed timestamps on the + file. All of these things are done automatically by a call to ZipEntry.Extract(). For this reason, the + ZipInputStream is generally recommended for when your application wants + to extract the data, without storing that data into a file. + + + + Aside from the obvious differences in programming model, there are some + differences in capability between the ZipFile class and the + ZipInputStream class. + + + + + ZipFile can be used to create or update zip files, or read and extract + zip files. ZipInputStream can be used only to read and extract zip + files. If you want to use a stream to create zip files, check out the . + + + + ZipInputStream cannot read segmented or spanned + zip files. + + + + ZipInputStream will not read Zip file comments. + + + + When reading larger files, ZipInputStream will always underperform + ZipFile. This is because the ZipInputStream does a full scan on the + zip file, while the ZipFile class reads the central directory of the + zip file. + + + + + + + + The stream to read. It must be readable. This stream will be closed at + the time the ZipInputStream is closed. + + + + + This example shows how to read a zip file, and extract entries, using the + ZipInputStream class. + + + private void Unzip() + { + byte[] buffer= new byte[2048]; + int n; + using (var raw = File.Open(inputFileName, FileMode.Open, FileAccess.Read)) + { + using (var input= new ZipInputStream(raw)) + { + ZipEntry e; + while (( e = input.GetNextEntry()) != null) + { + if (e.IsDirectory) continue; + string outputPath = Path.Combine(extractDir, e.FileName); + using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite)) + { + while ((n= input.Read(buffer, 0, buffer.Length)) > 0) + { + output.Write(buffer,0,n); + } + } + } + } + } + } + + + + Private Sub UnZip() + Dim inputFileName As String = "MyArchive.zip" + Dim extractDir As String = "extract" + Dim buffer As Byte() = New Byte(2048) {} + Using raw As FileStream = File.Open(inputFileName, FileMode.Open, FileAccess.Read) + Using input As ZipInputStream = New ZipInputStream(raw) + Dim e As ZipEntry + Do While (Not e = input.GetNextEntry Is Nothing) + If Not e.IsDirectory Then + Using output As FileStream = File.Open(Path.Combine(extractDir, e.FileName), _ + FileMode.Create, FileAccess.ReadWrite) + Dim n As Integer + Do While (n = input.Read(buffer, 0, buffer.Length) > 0) + output.Write(buffer, 0, n) + Loop + End Using + End If + Loop + End Using + End Using + End Sub + + + + + + Create a ZipInputStream, given the name of an existing zip file. + + + + + + This constructor opens a FileStream for the given zipfile, and + wraps a ZipInputStream around that. See the documentation for the + constructor for full details. + + + + While the class is generally easier + to use, this class provides an alternative to those + applications that want to read from a zipfile directly, + using a . + + + + + + The name of the filesystem file to read. + + + + + This example shows how to read a zip file, and extract entries, using the + ZipInputStream class. + + + private void Unzip() + { + byte[] buffer= new byte[2048]; + int n; + using (var input= new ZipInputStream(inputFileName)) + { + ZipEntry e; + while (( e = input.GetNextEntry()) != null) + { + if (e.IsDirectory) continue; + string outputPath = Path.Combine(extractDir, e.FileName); + using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite)) + { + while ((n= input.Read(buffer, 0, buffer.Length)) > 0) + { + output.Write(buffer,0,n); + } + } + } + } + } + + + + Private Sub UnZip() + Dim inputFileName As String = "MyArchive.zip" + Dim extractDir As String = "extract" + Dim buffer As Byte() = New Byte(2048) {} + Using input As ZipInputStream = New ZipInputStream(inputFileName) + Dim e As ZipEntry + Do While (Not e = input.GetNextEntry Is Nothing) + If Not e.IsDirectory Then + Using output As FileStream = File.Open(Path.Combine(extractDir, e.FileName), _ + FileMode.Create, FileAccess.ReadWrite) + Dim n As Integer + Do While (n = input.Read(buffer, 0, buffer.Length) > 0) + output.Write(buffer, 0, n) + Loop + End Using + End If + Loop + End Using + End Sub + + + + + + Create a ZipInputStream, explicitly specifying whether to + keep the underlying stream open. + + + + See the documentation for the ZipInputStream(Stream) + constructor for a discussion of the class, and an example of how to use the class. + + + + The stream to read from. It must be readable. + + + + true if the application would like the stream + to remain open after the ZipInputStream has been closed. + + + + Provides a string representation of the instance. + + + This can be useful for debugging purposes. + + + a string representation of the instance. + + + + The text encoding to use when reading entries into the zip archive, for + those entries whose filenames or comments cannot be encoded with the + default (IBM437) encoding. + + + + + In its + zip specification, PKWare describes two options for encoding + filenames and comments: using IBM437 or UTF-8. But, some archiving tools + or libraries do not follow the specification, and instead encode + characters using the system default code page. For example, WinRAR when + run on a machine in Shanghai may encode filenames with the Big-5 Chinese + (950) code page. This behavior is contrary to the Zip specification, but + it occurs anyway. + + + + When using DotNetZip to read zip archives that use something other than + UTF-8 or IBM437, set this property to specify the code page to use when + reading encoded filenames and comments for each ZipEntry in the zip + file. + + + + This property is "provisional". When the entry in the zip archive is not + explicitly marked as using UTF-8, then IBM437 is used to decode filenames + and comments. If a loss of data would result from using IBM436 - + specifically when encoding and decoding is not reflexive - the codepage + specified here is used. It is possible, therefore, to have a given entry + with a Comment encoded in IBM437 and a FileName encoded with + the specified "provisional" codepage. + + + + When a zip file uses an arbitrary, non-UTF8 code page for encoding, there + is no standard way for the reader application - whether DotNetZip, WinZip, + WinRar, or something else - to know which codepage has been used for the + entries. Readers of zip files are not able to inspect the zip file and + determine the codepage that was used for the entries contained within it. + It is left to the application or user to determine the necessary codepage + when reading zip files encoded this way. If you use an incorrect codepage + when reading a zipfile, you will get entries with filenames that are + incorrect, and the incorrect filenames may even contain characters that + are not legal for use within filenames in Windows. Extracting entries with + illegal characters in the filenames will lead to exceptions. It's too bad, + but this is just the way things are with code pages in zip files. Caveat + Emptor. + + + + + + + Size of the work buffer to use for the ZLIB codec during decompression. + + + + Setting this affects the performance and memory efficiency of compression + and decompression. For larger files, setting this to a larger size may + improve performance, but the exact numbers vary depending on available + memory, and a bunch of other variables. I don't have good firm + recommendations on how to set it. You'll have to test it yourself. Or + just leave it alone and accept the default. + + + + + Sets the password to be used on the ZipInputStream instance. + + + + + + When reading a zip archive, this password is used to read and decrypt the + entries that are encrypted within the zip file. When entries within a zip + file use different passwords, set the appropriate password for the entry + before the first call to Read() for each entry. + + + + When reading an entry that is not encrypted, the value of this property is + ignored. + + + + + + + This example uses the ZipInputStream to read and extract entries from a + zip file, using a potentially different password for each entry. + + + byte[] buffer= new byte[2048]; + int n; + using (var raw = File.Open(_inputFileName, FileMode.Open, FileAccess.Read )) + { + using (var input= new ZipInputStream(raw)) + { + ZipEntry e; + while (( e = input.GetNextEntry()) != null) + { + input.Password = PasswordForEntry(e.FileName); + if (e.IsDirectory) continue; + string outputPath = Path.Combine(_extractDir, e.FileName); + using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite)) + { + while ((n= input.Read(buffer,0,buffer.Length)) > 0) + { + output.Write(buffer,0,n); + } + } + } + } + } + + + + + + + Read the data from the stream into the buffer. + + + + + The data for the zipentry will be decrypted and uncompressed, as + necessary, before being copied into the buffer. + + + + You must set the property before calling + Read() the first time for an encrypted entry. To determine if an + entry is encrypted and requires a password, check the ZipEntry.Encryption property. + + + + The buffer to hold the data read from the stream. + the offset within the buffer to copy the first byte read. + the number of bytes to read. + the number of bytes read, after decryption and decompression. + + + + Read the next entry from the zip file. + + + + + Call this method just before calling , + to position the pointer in the zip file to the next entry that can be + read. Subsequent calls to Read(), will decrypt and decompress the + data in the zip file, until Read() returns 0. + + + + Each time you call GetNextEntry(), the pointer in the wrapped + stream is moved to the next entry in the zip file. If you call , and thus re-position the pointer within + the file, you will need to call GetNextEntry() again, to insure + that the file pointer is positioned at the beginning of a zip entry. + + + + This method returns the ZipEntry. Using a stream approach, you will + read the raw bytes for an entry in a zip file via calls to Read(). + Alternatively, you can extract an entry into a file, or a stream, by + calling , or one of its siblings. + + + + + + The ZipEntry read. Returns null (or Nothing in VB) if there are no more + entries in the zip file. + + + + + + Dispose the stream. + + + + + This method disposes the ZipInputStream. It may also close the + underlying stream, depending on which constructor was used. + + + + Typically the application will call Dispose() implicitly, via + a using statement in C#, or a Using statement in VB. + + + + Application code won't call this code directly. This method may + be invoked in two distinct scenarios. If disposing == true, the + method has been called directly or indirectly by a user's code, + for example via the public Dispose() method. In this case, both + managed and unmanaged resources can be referenced and disposed. + If disposing == false, the method has been called by the runtime + from inside the object finalizer and this method should not + reference other objects; in that case only unmanaged resources + must be referenced or disposed. + + + + + true if the Dispose method was invoked by user code. + + + + + Always returns true. + + + + + Returns the value of CanSeek for the underlying (wrapped) stream. + + + + + Always returns false. + + + + + Returns the length of the underlying stream. + + + + + Gets or sets the position of the underlying stream. + + + Setting the position is equivalent to calling Seek(value, SeekOrigin.Begin). + + + + + This is a no-op. + + + + + This method always throws a NotSupportedException. + + ignored + ignored + ignored + + + + This method seeks in the underlying stream. + + + + + Call this method if you want to seek around within the zip file for random access. + + + + Applications can intermix calls to Seek() with calls to . After a call to Seek(), + GetNextEntry() will get the next ZipEntry that falls after + the current position in the input stream. You're on your own for finding + out just where to seek in the stream, to get to the various entries. + + + + + the offset point to seek to + the reference point from which to seek + The new position + + + + This method always throws a NotSupportedException. + + ignored + + + + Provides a stream metaphor for generating zip files. + + + + + This class writes zip files, as defined in the specification + for zip files described by PKWare. The compression for this + implementation is provided by a managed-code version of Zlib, included with + DotNetZip in the classes in the Ionic.Zlib namespace. + + + + This class provides an alternative programming model to the one enabled by the + class. Use this when creating zip files, as an + alternative to the class, when you would like to use a + Stream type to write the zip file. + + + + Both the ZipOutputStream class and the ZipFile class can be used + to create zip files. Both of them support many of the common zip features, + including Unicode, different compression levels, and ZIP64. They provide + very similar performance when creating zip files. + + + + The ZipFile class is generally easier to use than + ZipOutputStream and should be considered a higher-level interface. For + example, when creating a zip file via calls to the PutNextEntry() and + Write() methods on the ZipOutputStream class, the caller is + responsible for opening the file, reading the bytes from the file, writing + those bytes into the ZipOutputStream, setting the attributes on the + ZipEntry, and setting the created, last modified, and last accessed + timestamps on the zip entry. All of these things are done automatically by a + call to ZipFile.AddFile(). + For this reason, the ZipOutputStream is generally recommended for use + only when your application emits arbitrary data, not necessarily data from a + filesystem file, directly into a zip file, and does so using a Stream + metaphor. + + + + Aside from the differences in programming model, there are other + differences in capability between the two classes. + + + + + ZipFile can be used to read and extract zip files, in addition to + creating zip files. ZipOutputStream cannot read zip files. If you want + to use a stream to read zip files, check out the class. + + + + ZipOutputStream does not support the creation of segmented or spanned + zip files. + + + + ZipOutputStream cannot produce a self-extracting archive. + + + + + Be aware that the ZipOutputStream class implements the interface. In order for + ZipOutputStream to produce a valid zip file, you use use it within + a using clause (Using in VB), or call the Dispose() method + explicitly. See the examples for how to employ a using clause. + + + + Also, a note regarding compression performance: On the desktop .NET + Framework, DotNetZip can use a multi-threaded compression implementation + that provides significant speed increases on large files, over 300k or so, + at the cost of increased memory use at runtime. (The output of the + compression is almost exactly the same size). But, the multi-threaded + approach incurs a performance hit on smaller files. There's no way for the + ZipOutputStream to know whether parallel compression will be beneficial, + because the ZipOutputStream does not know how much data you will write + through the stream. You may wish to set the property to zero, if you are compressing + large files through ZipOutputStream. This will cause parallel + compression to be used, always. + + + + + + Create a ZipOutputStream, wrapping an existing stream. + + + + + The class is generally easier to use when creating + zip files. The ZipOutputStream offers a different metaphor for creating a + zip file, based on the class. + + + + + + The stream to wrap. It must be writable. This stream will be closed at + the time the ZipOutputStream is closed. + + + + + This example shows how to create a zip file, using the + ZipOutputStream class. + + + private void Zipup() + { + if (filesToZip.Count == 0) + { + System.Console.WriteLine("Nothing to do."); + return; + } + + using (var raw = File.Open(_outputFileName, FileMode.Create, FileAccess.ReadWrite )) + { + using (var output= new ZipOutputStream(raw)) + { + output.Password = "VerySecret!"; + output.Encryption = EncryptionAlgorithm.WinZipAes256; + + foreach (string inputFileName in filesToZip) + { + System.Console.WriteLine("file: {0}", inputFileName); + + output.PutNextEntry(inputFileName); + using (var input = File.Open(inputFileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Write )) + { + byte[] buffer= new byte[2048]; + int n; + while ((n= input.Read(buffer,0,buffer.Length)) > 0) + { + output.Write(buffer,0,n); + } + } + } + } + } + } + + + + Private Sub Zipup() + Dim outputFileName As String = "XmlData.zip" + Dim filesToZip As String() = Directory.GetFiles(".", "*.xml") + If (filesToZip.Length = 0) Then + Console.WriteLine("Nothing to do.") + Else + Using raw As FileStream = File.Open(outputFileName, FileMode.Create, FileAccess.ReadWrite) + Using output As ZipOutputStream = New ZipOutputStream(raw) + output.Password = "VerySecret!" + output.Encryption = EncryptionAlgorithm.WinZipAes256 + Dim inputFileName As String + For Each inputFileName In filesToZip + Console.WriteLine("file: {0}", inputFileName) + output.PutNextEntry(inputFileName) + Using input As FileStream = File.Open(inputFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) + Dim n As Integer + Dim buffer As Byte() = New Byte(2048) {} + Do While (n = input.Read(buffer, 0, buffer.Length) > 0) + output.Write(buffer, 0, n) + Loop + End Using + Next + End Using + End Using + End If + End Sub + + + + + + Create a ZipOutputStream that writes to a filesystem file. + + + + The class is generally easier to use when creating + zip files. The ZipOutputStream offers a different metaphor for creating a + zip file, based on the class. + + + + The name of the zip file to create. + + + + + This example shows how to create a zip file, using the + ZipOutputStream class. + + + private void Zipup() + { + if (filesToZip.Count == 0) + { + System.Console.WriteLine("Nothing to do."); + return; + } + + using (var output= new ZipOutputStream(outputFileName)) + { + output.Password = "VerySecret!"; + output.Encryption = EncryptionAlgorithm.WinZipAes256; + + foreach (string inputFileName in filesToZip) + { + System.Console.WriteLine("file: {0}", inputFileName); + + output.PutNextEntry(inputFileName); + using (var input = File.Open(inputFileName, FileMode.Open, FileAccess.Read, + FileShare.Read | FileShare.Write )) + { + byte[] buffer= new byte[2048]; + int n; + while ((n= input.Read(buffer,0,buffer.Length)) > 0) + { + output.Write(buffer,0,n); + } + } + } + } + } + + + + Private Sub Zipup() + Dim outputFileName As String = "XmlData.zip" + Dim filesToZip As String() = Directory.GetFiles(".", "*.xml") + If (filesToZip.Length = 0) Then + Console.WriteLine("Nothing to do.") + Else + Using output As ZipOutputStream = New ZipOutputStream(outputFileName) + output.Password = "VerySecret!" + output.Encryption = EncryptionAlgorithm.WinZipAes256 + Dim inputFileName As String + For Each inputFileName In filesToZip + Console.WriteLine("file: {0}", inputFileName) + output.PutNextEntry(inputFileName) + Using input As FileStream = File.Open(inputFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) + Dim n As Integer + Dim buffer As Byte() = New Byte(2048) {} + Do While (n = input.Read(buffer, 0, buffer.Length) > 0) + output.Write(buffer, 0, n) + Loop + End Using + Next + End Using + End If + End Sub + + + + + + Create a ZipOutputStream. + + + + See the documentation for the ZipOutputStream(Stream) + constructor for an example. + + + + The stream to wrap. It must be writable. + + + + true if the application would like the stream + to remain open after the ZipOutputStream has been closed. + + + + Provides a string representation of the instance. + + + This can be useful for debugging purposes. + + + a string representation of the instance. + + + + Sets the password to be used on the ZipOutputStream instance. + + + + + + When writing a zip archive, this password is applied to the entries, not + to the zip archive itself. It applies to any ZipEntry subsequently + written to the ZipOutputStream. + + + + Using a password does not encrypt or protect the "directory" of the + archive - the list of entries contained in the archive. If you set the + Password property, the password actually applies to individual + entries that are added to the archive, subsequent to the setting of this + property. The list of filenames in the archive that is eventually created + will appear in clear text, but the contents of the individual files are + encrypted. This is how Zip encryption works. + + + + If you set this property, and then add a set of entries to the archive via + calls to PutNextEntry, then each entry is encrypted with that + password. You may also want to change the password between adding + different entries. If you set the password, add an entry, then set the + password to null (Nothing in VB), and add another entry, the + first entry is encrypted and the second is not. + + + + When setting the Password, you may also want to explicitly set the property, to specify how to encrypt the entries added + to the ZipFile. If you set the Password to a non-null value and do not + set , then PKZip 2.0 ("Weak") encryption is used. + This encryption is relatively weak but is very interoperable. If + you set the password to a null value (Nothing in VB), + Encryption is reset to None. + + + + Special case: if you wrap a ZipOutputStream around a non-seekable stream, + and use encryption, and emit an entry of zero bytes, the Close() or + PutNextEntry() following the entry will throw an exception. + + + + + + + The Encryption to use for entries added to the ZipOutputStream. + + + + + The specified Encryption is applied to the entries subsequently + written to the ZipOutputStream instance. + + + + If you set this to something other than + EncryptionAlgorithm.None, you will also need to set the + to a non-null, non-empty value in + order to actually get encryption on the entry. + + + + + ZipOutputStream.Password + ZipEntry.Encryption + + + + Size of the work buffer to use for the ZLIB codec during compression. + + + + Setting this may affect performance. For larger files, setting this to a + larger size may improve performance, but I'm not sure. Sorry, I don't + currently have good recommendations on how to set it. You can test it if + you like. + + + + + The compression strategy to use for all entries. + + + + Set the Strategy used by the ZLIB-compatible compressor, when compressing + data for the entries in the zip archive. Different compression strategies + work better on different sorts of data. The strategy parameter can affect + the compression ratio and the speed of compression but not the correctness + of the compresssion. For more information see . + + + + + The type of timestamp attached to the ZipEntry. + + + + Set this in order to specify the kind of timestamp that should be emitted + into the zip file for each entry. + + + + + Sets the compression level to be used for entries subsequently added to + the zip archive. + + + + + Varying the compression level used on entries can affect the + size-vs-speed tradeoff when compression and decompressing data streams + or files. + + + + As with some other properties on the ZipOutputStream class, like , and , + setting this property on a ZipOutputStream + instance will cause the specified CompressionLevel to be used on all + items that are subsequently added to the + ZipOutputStream instance. + + + + If you do not set this property, the default compression level is used, + which normally gives a good balance of compression efficiency and + compression speed. In some tests, using BestCompression can + double the time it takes to compress, while delivering just a small + increase in compression efficiency. This behavior will vary with the + type of data you compress. If you are in doubt, just leave this setting + alone, and accept the default. + + + + + + The compression method used on each entry added to the ZipOutputStream. + + + + + A comment attached to the zip archive. + + + + + + The application sets this property to specify a comment to be embedded + into the generated zip archive. + + + + According to PKWARE's + zip specification, the comment is not encrypted, even if there is a + password set on the zip file. + + + + The specification does not describe how to indicate the encoding used + on a comment string. Many "compliant" zip tools and libraries use + IBM437 as the code page for comments; DotNetZip, too, follows that + practice. On the other hand, there are situations where you want a + Comment to be encoded with something else, for example using code page + 950 "Big-5 Chinese". To fill that need, DotNetZip will encode the + comment following the same procedure it follows for encoding + filenames: (a) if is + Never, it uses the default encoding (IBM437). (b) if is Always, it always uses the + alternate encoding (). (c) if is AsNecessary, it uses the + alternate encoding only if the default encoding is not sufficient for + encoding the comment - in other words if decoding the result does not + produce the original string. This decision is taken at the time of + the call to ZipFile.Save(). + + + + + + + Specify whether to use ZIP64 extensions when saving a zip archive. + + + + + The default value for the property is . is + safest, in the sense that you will not get an Exception if a + pre-ZIP64 limit is exceeded. + + + + You must set this property before calling Write(). + + + + + + + Indicates whether ZIP64 extensions were used when saving the zip archive. + + + + The value is defined only after the ZipOutputStream has been closed. + + + + + Whether the ZipOutputStream should use case-insensitive comparisons when + checking for uniqueness of zip entries. + + + + + Though the zip specification doesn't prohibit zipfiles with duplicate + entries, Sane zip files have no duplicates, and the DotNetZip library + cannot create zip files with duplicate entries. If an application attempts + to call with a name that duplicates one + already used within the archive, the library will throw an Exception. + + + This property allows the application to specify whether the + ZipOutputStream instance considers ordinal case when checking for + uniqueness of zip entries. + + + + + + Indicates whether to encode entry filenames and entry comments using + Unicode (UTF-8). + + + + + The + PKWare zip specification provides for encoding file names and file + comments in either the IBM437 code page, or in UTF-8. This flag selects + the encoding according to that specification. By default, this flag is + false, and filenames and comments are encoded into the zip file in the + IBM437 codepage. Setting this flag to true will specify that filenames + and comments that cannot be encoded with IBM437 will be encoded with + UTF-8. + + + + Zip files created with strict adherence to the PKWare specification with + respect to UTF-8 encoding can contain entries with filenames containing + any combination of Unicode characters, including the full range of + characters from Chinese, Latin, Hebrew, Greek, Cyrillic, and many other + alphabets. However, because at this time, the UTF-8 portion of the PKWare + specification is not broadly supported by other zip libraries and + utilities, such zip files may not be readable by your favorite zip tool or + archiver. In other words, interoperability will decrease if you set this + flag to true. + + + + In particular, Zip files created with strict adherence to the PKWare + specification with respect to UTF-8 encoding will not work well with + Explorer in Windows XP or Windows Vista, because Windows compressed + folders, as far as I know, do not support UTF-8 in zip files. Vista can + read the zip files, but shows the filenames incorrectly. Unpacking from + Windows Vista Explorer will result in filenames that have rubbish + characters in place of the high-order UTF-8 bytes. + + + + Also, zip files that use UTF-8 encoding will not work well with Java + applications that use the java.util.zip classes, as of v5.0 of the Java + runtime. The Java runtime does not correctly implement the PKWare + specification in this regard. + + + + As a result, we have the unfortunate situation that "correct" behavior by + the DotNetZip library with regard to Unicode encoding of filenames during + zip creation will result in zip files that are readable by strictly + compliant and current tools (for example the most recent release of the + commercial WinZip tool); but these zip files will not be readable by + various other tools or libraries, including Windows Explorer. + + + + The DotNetZip library can read and write zip files with UTF8-encoded + entries, according to the PKware spec. If you use DotNetZip for both + creating and reading the zip file, and you use UTF-8, there will be no + loss of information in the filenames. For example, using a self-extractor + created by this library will allow you to unpack files correctly with no + loss of information in the filenames. + + + + If you do not set this flag, it will remain false. If this flag is false, + the ZipOutputStream will encode all filenames and comments using + the IBM437 codepage. This can cause "loss of information" on some + filenames, but the resulting zipfile will be more interoperable with other + utilities. As an example of the loss of information, diacritics can be + lost. The o-tilde character will be down-coded to plain o. The c with a + cedilla (Unicode 0xE7) used in Portugese will be downcoded to a c. + Likewise, the O-stroke character (Unicode 248), used in Danish and + Norwegian, will be down-coded to plain o. Chinese characters cannot be + represented in codepage IBM437; when using the default encoding, Chinese + characters in filenames will be represented as ?. These are all examples + of "information loss". + + + + The loss of information associated to the use of the IBM437 encoding is + inconvenient, and can also lead to runtime errors. For example, using + IBM437, any sequence of 4 Chinese characters will be encoded as ????. If + your application creates a ZipOutputStream, does not set the + encoding, then adds two files, each with names of four Chinese characters + each, this will result in a duplicate filename exception. In the case + where you add a single file with a name containing four Chinese + characters, the zipfile will save properly, but extracting that file + later, with any zip tool, will result in an error, because the question + mark is not legal for use within filenames on Windows. These are just a + few examples of the problems associated to loss of information. + + + + This flag is independent of the encoding of the content within the entries + in the zip file. Think of the zip file as a container - it supports an + encoding. Within the container are other "containers" - the file entries + themselves. The encoding within those entries is independent of the + encoding of the zip archive container for those entries. + + + + Rather than specify the encoding in a binary fashion using this flag, an + application can specify an arbitrary encoding via the property. Setting the encoding + explicitly when creating zip archives will result in non-compliant zip + files that, curiously, are fairly interoperable. The challenge is, the + PKWare specification does not provide for a way to specify that an entry + in a zip archive uses a code page that is neither IBM437 nor UTF-8. + Therefore if you set the encoding explicitly when creating a zip archive, + you must take care upon reading the zip archive to use the same code page. + If you get it wrong, the behavior is undefined and may result in incorrect + filenames, exceptions, stomach upset, hair loss, and acne. + + + + + + + The text encoding to use when emitting entries into the zip archive, for + those entries whose filenames or comments cannot be encoded with the + default (IBM437) encoding. + + + + + In its + zip specification, PKWare describes two options for encoding + filenames and comments: using IBM437 or UTF-8. But, some archiving tools + or libraries do not follow the specification, and instead encode + characters using the system default code page. For example, WinRAR when + run on a machine in Shanghai may encode filenames with the Big-5 Chinese + (950) code page. This behavior is contrary to the Zip specification, but + it occurs anyway. + + + + When using DotNetZip to write zip archives that will be read by one of + these other archivers, set this property to specify the code page to use + when encoding the and for each ZipEntry in the zip file, for + values that cannot be encoded with the default codepage for zip files, + IBM437. This is why this property is "provisional". In all cases, IBM437 + is used where possible, in other words, where no loss of data would + result. It is possible, therefore, to have a given entry with a + Comment encoded in IBM437 and a FileName encoded with the + specified "provisional" codepage. + + + + Be aware that a zip file created after you've explicitly set the + ProvisionalAlternateEncoding property to a value other than + IBM437 may not be compliant to the PKWare specification, and may not be + readable by compliant archivers. On the other hand, many (most?) + archivers are non-compliant and can read zip files created in arbitrary + code pages. The trick is to use or specify the proper codepage when + reading the zip. + + + + When creating a zip archive using this library, it is possible to change + the value of ProvisionalAlternateEncoding between each entry you + add, and between adding entries and the call to Close(). Don't do + this. It will likely result in a zipfile that is not readable. For best + interoperability, either leave ProvisionalAlternateEncoding + alone, or specify it only once, before adding any entries to the + ZipOutputStream instance. There is one exception to this + recommendation, described later. + + + + When using an arbitrary, non-UTF8 code page for encoding, there is no + standard way for the creator application - whether DotNetZip, WinZip, + WinRar, or something else - to formally specify in the zip file which + codepage has been used for the entries. As a result, readers of zip files + are not able to inspect the zip file and determine the codepage that was + used for the entries contained within it. It is left to the application + or user to determine the necessary codepage when reading zip files encoded + this way. If you use an incorrect codepage when reading a zipfile, you + will get entries with filenames that are incorrect, and the incorrect + filenames may even contain characters that are not legal for use within + filenames in Windows. Extracting entries with illegal characters in the + filenames will lead to exceptions. It's too bad, but this is just the way + things are with code pages in zip files. Caveat Emptor. + + + + One possible approach for specifying the code page for a given zip file is + to describe the code page in a human-readable form in the Zip comment. For + example, the comment may read "Entries in this archive are encoded in the + Big5 code page". For maximum interoperability, the zip comment in this + case should be encoded in the default, IBM437 code page. In this case, + the zip comment is encoded using a different page than the filenames. To + do this, Specify ProvisionalAlternateEncoding to your desired + region-specific code page, once before adding any entries, and then set + the property and reset + ProvisionalAlternateEncoding to IBM437 before calling Close(). + + + + + + A Text Encoding to use when encoding the filenames and comments for + all the ZipEntry items, during a ZipFile.Save() operation. + + + + Whether the encoding specified here is used during the save depends + on . + + + + + + A flag that tells if and when this instance should apply + AlternateEncoding to encode the filenames and comments associated to + of ZipEntry objects contained within this instance. + + + + + The default text encoding used in zip archives. It is numeric 437, also + known as IBM437. + + + + + + The size threshold for an entry, above which a parallel deflate is used. + + + + + + DotNetZip will use multiple threads to compress any ZipEntry, when + the CompressionMethod is Deflate, and if the entry is + larger than the given size. Zero means "always use parallel + deflate", while -1 means "never use parallel deflate". + + + + If the entry size cannot be known before compression, as with any entry + added via a ZipOutputStream, then Parallel deflate will never be + performed, unless the value of this property is zero. + + + + A parallel deflate operations will speed up the compression of + large files, on computers with multiple CPUs or multiple CPU + cores. For files above 1mb, on a dual core or dual-cpu (2p) + machine, the time required to compress the file can be 70% of the + single-threaded deflate. For very large files on 4p machines the + compression can be done in 30% of the normal time. The downside + is that parallel deflate consumes extra memory during the deflate, + and the deflation is slightly less effective. + + + + Parallel deflate tends to not be as effective as single-threaded deflate + because the original data stream is split into multiple independent + buffers, each of which is compressed in parallel. But because they are + treated independently, there is no opportunity to share compression + dictionaries, and additional framing bytes must be added to the output + stream. For that reason, a deflated stream may be slightly larger when + compressed using parallel deflate, as compared to a traditional + single-threaded deflate. For files of about 512k, the increase over the + normal deflate is as much as 5% of the total compressed size. For larger + files, the difference can be as small as 0.1%. + + + + Multi-threaded compression does not give as much an advantage when using + Encryption. This is primarily because encryption tends to slow down + the entire pipeline. Also, multi-threaded compression gives less of an + advantage when using lower compression levels, for example . You may have to perform + some tests to determine the best approach for your situation. + + + + The default value for this property is -1, which means parallel + compression will not be performed unless you set it to zero. + + + + + + + The maximum number of buffer pairs to use when performing + parallel compression. + + + + + This property sets an upper limit on the number of memory + buffer pairs to create when performing parallel + compression. The implementation of the parallel + compression stream allocates multiple buffers to + facilitate parallel compression. As each buffer fills up, + the stream uses + ThreadPool.QueueUserWorkItem() to compress those + buffers in a background threadpool thread. After a buffer + is compressed, it is re-ordered and written to the output + stream. + + + + A higher number of buffer pairs enables a higher degree of + parallelism, which tends to increase the speed of compression on + multi-cpu computers. On the other hand, a higher number of buffer + pairs also implies a larger memory consumption, more active worker + threads, and a higher cpu utilization for any compression. This + property enables the application to limit its memory consumption and + CPU utilization behavior depending on requirements. + + + + For each compression "task" that occurs in parallel, there are 2 + buffers allocated: one for input and one for output. This property + sets a limit for the number of pairs. The total amount of storage + space allocated for buffering will then be (N*S*2), where N is the + number of buffer pairs, S is the size of each buffer (). By default, DotNetZip allocates 4 buffer + pairs per CPU core, so if your machine has 4 cores, and you retain + the default buffer size of 128k, then the + ParallelDeflateOutputStream will use 4 * 4 * 2 * 128kb of buffer + memory in total, or 4mb, in blocks of 128kb. If you then set this + property to 8, then the number will be 8 * 2 * 128kb of buffer + memory, or 2mb. + + + + CPU utilization will also go up with additional buffers, because a + larger number of buffer pairs allows a larger number of background + threads to compress in parallel. If you find that parallel + compression is consuming too much memory or CPU, you can adjust this + value downward. + + + + The default value is 16. Different values may deliver better or + worse results, depending on your priorities and the dynamic + performance characteristics of your storage and compute resources. + + + + This property is not the number of buffer pairs to use; it is an + upper limit. An illustration: Suppose you have an application that + uses the default value of this property (which is 16), and it runs + on a machine with 2 CPU cores. In that case, DotNetZip will allocate + 4 buffer pairs per CPU core, for a total of 8 pairs. The upper + limit specified by this property has no effect. + + + + The application can set this value at any time, but it is + effective only if set before calling + ZipOutputStream.Write() for the first time. + + + + + + + + + Returns true if an entry by the given name has already been written + to the ZipOutputStream. + + + + The name of the entry to scan for. + + + + true if an entry by the given name has already been written. + + + + + Write the data from the buffer to the stream. + + + + As the application writes data into this stream, the data may be + compressed and encrypted before being written out to the underlying + stream, depending on the settings of the + and the properties. + + + The buffer holding data to write to the stream. + the offset within that data array to find the first byte to write. + the number of bytes to write. + + + + Specify the name of the next entry that will be written to the zip file. + + + + + Call this method just before calling , to + specify the name of the entry that the next set of bytes written to + the ZipOutputStream belongs to. All subsequent calls to Write, + until the next call to PutNextEntry, + will be inserted into the named entry in the zip file. + + + + If the used in PutNextEntry() ends in + a slash, then the entry added is marked as a directory. Because directory + entries do not contain data, a call to Write(), before an + intervening additional call to PutNextEntry(), will throw an + exception. + + + + If you don't call Write() between two calls to + PutNextEntry(), the first entry is inserted into the zip file as a + file of zero size. This may be what you want. + + + + Because PutNextEntry() closes out the prior entry, if any, this + method may throw if there is a problem with the prior entry. + + + + This method returns the ZipEntry. You can modify public properties + on the ZipEntry, such as , , and so on, until the first call to + ZipOutputStream.Write(), or until the next call to + PutNextEntry(). If you modify the ZipEntry after + having called Write(), you may get a runtime exception, or you may + silently get an invalid zip archive. + + + + + + + This example shows how to create a zip file, using the + ZipOutputStream class. + + + private void Zipup() + { + using (FileStream fs raw = File.Open(_outputFileName, FileMode.Create, FileAccess.ReadWrite )) + { + using (var output= new ZipOutputStream(fs)) + { + output.Password = "VerySecret!"; + output.Encryption = EncryptionAlgorithm.WinZipAes256; + output.PutNextEntry("entry1.txt"); + byte[] buffer= System.Text.Encoding.ASCII.GetBytes("This is the content for entry #1."); + output.Write(buffer,0,buffer.Length); + output.PutNextEntry("entry2.txt"); // this will be zero length + output.PutNextEntry("entry3.txt"); + buffer= System.Text.Encoding.ASCII.GetBytes("This is the content for entry #3."); + output.Write(buffer,0,buffer.Length); + } + } + } + + + + + The name of the entry to be added, including any path to be used + within the zip file. + + + + The ZipEntry created. + + + + + + Dispose the stream + + + + + This method writes the Zip Central directory, then closes the stream. The + application must call Dispose() (or Close) in order to produce a valid zip file. + + + + Typically the application will call Dispose() implicitly, via a using + statement in C#, or a Using statement in VB. + + + + + set this to true, always. + + + + Always returns false. + + + + + Always returns false. + + + + + Always returns true. + + + + + Always returns a NotSupportedException. + + + + + Setting this property always returns a NotSupportedException. Getting it + returns the value of the Position on the underlying stream. + + + + + This is a no-op. + + + + + This method always throws a NotSupportedException. + + ignored + ignored + ignored + nothing + + + + This method always throws a NotSupportedException. + + ignored + ignored + nothing + + + + This method always throws a NotSupportedException. + + ignored + + + + Sort-of like a factory method, ForUpdate is used only when + the application needs to update the zip entry metadata for + a segmented zip file, when the starting segment is earlier + than the ending segment, for a particular entry. + + + + The update is always contiguous, never rolls over. As a + result, this method doesn't need to return a ZSS; it can + simply return a FileStream. That's why it's "sort of" + like a Factory method. + + + Caller must Close/Dispose the stream object returned by + this method. + + + + + + Name of the filesystem file corresponding to the current segment. + + + + The name is not always the name currently being used in the + filesystem. When rwMode is RwMode.Write, the filesystem file has a + temporary name until the stream is closed or until the next segment is + started. + + + + + + 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 + + + + Write to the stream. + + the buffer from which to write + the offset at which to start writing + the number of bytes to write + + + + Enumerates the options for a logical conjunction. This enum is intended for use + internally by the FileSelector class. + + + + + FileSelector encapsulates logic that selects files from a source - a zip file + or the filesystem - based on a set of criteria. This class is used internally + by the DotNetZip library, in particular for the AddSelectedFiles() methods. + This class can also be used independently of the zip capability in DotNetZip. + + + + + + The FileSelector class is used internally by the ZipFile class for selecting + files for inclusion into the ZipFile, when the method, or one of + its overloads, is called. It's also used for the methods. Typically, an + application that creates or manipulates Zip archives will not directly + interact with the FileSelector class. + + + + Some applications may wish to use the FileSelector class directly, to + select files from disk volumes based on a set of criteria, without creating or + querying Zip archives. The file selection criteria include: a pattern to + match the filename; the last modified, created, or last accessed time of the + file; the size of the file; and the attributes of the file. + + + + Consult the documentation for + for more information on specifying the selection criteria. + + + + + + + Constructor that allows the caller to specify file selection criteria. + + + + + This constructor allows the caller to specify a set of criteria for + selection of files. + + + + See for a description of + the syntax of the selectionCriteria string. + + + + By default the FileSelector will traverse NTFS Reparse Points. To + change this, use FileSelector(String, bool). + + + + The criteria for file selection. + + + + Constructor that allows the caller to specify file selection criteria. + + + + + This constructor allows the caller to specify a set of criteria for + selection of files. + + + + See for a description of + the syntax of the selectionCriteria string. + + + + The criteria for file selection. + + whether to traverse NTFS reparse points (junctions). + + + + + The string specifying which files to include when retrieving. + + + + + Specify the criteria in statements of 3 elements: a noun, an operator, + and a value. Consider the string "name != *.doc" . The noun is + "name". The operator is "!=", implying "Not Equal". The value is + "*.doc". That criterion, in English, says "all files with a name that + does not end in the .doc extension." + + + + Supported nouns include "name" (or "filename") for the filename; + "atime", "mtime", and "ctime" for last access time, last modfied time, + and created time of the file, respectively; "attributes" (or "attrs") + for the file attributes; "size" (or "length") for the file length + (uncompressed); and "type" for the type of object, either a file or a + directory. The "attributes", "type", and "name" nouns all support = + and != as operators. The "size", "atime", "mtime", and "ctime" nouns + support = and !=, and >, >=, <, <= as well. The times are + taken to be expressed in local time. + + + + Specify values for the file attributes as a string with one or more of + the characters H,R,S,A,I,L in any order, implying file attributes of + Hidden, ReadOnly, System, Archive, NotContextIndexed, and ReparsePoint + (symbolic link) respectively. + + + + To specify a time, use YYYY-MM-DD-HH:mm:ss or YYYY/MM/DD-HH:mm:ss as + the format. If you omit the HH:mm:ss portion, it is assumed to be + 00:00:00 (midnight). + + + + The value for a size criterion is expressed in integer quantities of + bytes, kilobytes (use k or kb after the number), megabytes (m or mb), + or gigabytes (g or gb). + + + + The value for a name is a pattern to match against the filename, + potentially including wildcards. The pattern follows CMD.exe glob + rules: * implies one or more of any character, while ? implies one + character. If the name pattern contains any slashes, it is matched to + the entire filename, including the path; otherwise, it is matched + against only the filename without the path. This means a pattern of + "*\*.*" matches all files one directory level deep, while a pattern of + "*.*" matches all files in all directories. + + + + To specify a name pattern that includes spaces, use single quotes + around the pattern. A pattern of "'* *.*'" will match all files that + have spaces in the filename. The full criteria string for that would + be "name = '* *.*'" . + + + + The value for a type criterion is either F (implying a file) or D + (implying a directory). + + + + Some examples: + + + + + criteria + Files retrieved + + + + name != *.xls + any file with an extension that is not .xls + + + + + name = *.mp3 + any file with a .mp3 extension. + + + + + *.mp3 + (same as above) any file with a .mp3 extension. + + + + + attributes = A + all files whose attributes include the Archive bit. + + + + + attributes != H + all files whose attributes do not include the Hidden bit. + + + + + mtime > 2009-01-01 + all files with a last modified time after January 1st, 2009. + + + + + ctime > 2009/01/01-03:00:00 + all files with a created time after 3am (local time), + on January 1st, 2009. + + + + + size > 2gb + all files whose uncompressed size is greater than 2gb. + + + + + type = D + all directories in the filesystem. + + + + + + You can combine criteria with the conjunctions AND, OR, and XOR. Using + a string like "name = *.txt AND size >= 100k" for the + selectionCriteria retrieves entries whose names end in .txt, and whose + uncompressed size is greater than or equal to 100 kilobytes. + + + + For more complex combinations of criteria, you can use parenthesis to + group clauses in the boolean logic. Absent parenthesis, the + precedence of the criterion atoms is determined by order of + appearance. Unlike the C# language, the AND conjunction does not take + precendence over the logical OR. This is important only in strings + that contain 3 or more criterion atoms. In other words, "name = *.txt + and size > 1000 or attributes = H" implies "((name = *.txt AND size + > 1000) OR attributes = H)" while "attributes = H OR name = *.txt + and size > 1000" evaluates to "((attributes = H OR name = *.txt) + AND size > 1000)". When in doubt, use parenthesis. + + + + Using time properties requires some extra care. If you want to + retrieve all entries that were last updated on 2009 February 14, + specify "mtime >= 2009-02-14 AND mtime < 2009-02-15". Read this + to say: all files updated after 12:00am on February 14th, until + 12:00am on February 15th. You can use the same bracketing approach to + specify any time period - a year, a month, a week, and so on. + + + + The syntax allows one special case: if you provide a string with no + spaces, it is treated as a pattern to match for the filename. + Therefore a string like "*.xls" will be equivalent to specifying "name + = *.xls". This "shorthand" notation does not work with compound + criteria. + + + + There is no logic in this class that insures that the inclusion + criteria are internally consistent. For example, it's possible to + specify criteria that says the file must have a size of less than 100 + bytes, as well as a size that is greater than 1000 bytes. Obviously + no file will ever satisfy such criteria, but this class does not check + for or detect such inconsistencies. + + + + + + Thrown in the setter if the value has an invalid syntax. + + + + + Indicates whether searches will traverse NTFS reparse points, like Junctions. + + + + + Returns a string representation of the FileSelector object. + + The string representation of the boolean logic statement of the file + selection criteria for this instance. + + + + Returns the names of the files in the specified directory + that fit the selection criteria specified in the FileSelector. + + + + This is equivalent to calling + with recurseDirectories = false. + + + + The name of the directory over which to apply the FileSelector + criteria. + + + + A collection of strings containing fully-qualified pathnames of files + that match the criteria specified in the FileSelector instance. + + + + + Returns the names of the files in the specified directory that fit the + selection criteria specified in the FileSelector, optionally recursing + through subdirectories. + + + + This method applies the file selection criteria contained in the + FileSelector to the files contained in the given directory, and + returns the names of files that conform to the criteria. + + + + The name of the directory over which to apply the FileSelector + criteria. + + + + Whether to recurse through subdirectories when applying the file + selection criteria. + + + + A collection of strings containing fully-qualified pathnames of files + that match the criteria specified in the FileSelector instance. + + + + + Retrieve the ZipEntry items in the ZipFile that conform to the specified criteria. + + + + + This method applies the criteria set in the FileSelector instance (as described in + the ) to the specified ZipFile. Using this + method, for example, you can retrieve all entries from the given ZipFile that + have filenames ending in .txt. + + + + Normally, applications would not call this method directly. This method is used + by the ZipFile class. + + + + Using the appropriate SelectionCriteria, you can retrieve entries based on size, + time, and attributes. See for a + description of the syntax of the SelectionCriteria string. + + + + + The ZipFile from which to retrieve entries. + + a collection of ZipEntry objects that conform to the criteria. + + + + Retrieve the ZipEntry items in the ZipFile that conform to the specified criteria. + + + + + This method applies the criteria set in the FileSelector instance (as described in + the ) to the specified ZipFile. Using this + method, for example, you can retrieve all entries from the given ZipFile that + have filenames ending in .txt. + + + + Normally, applications would not call this method directly. This method is used + by the ZipFile class. + + + + This overload allows the selection of ZipEntry instances from the ZipFile to be restricted + to entries contained within a particular directory in the ZipFile. + + + + Using the appropriate SelectionCriteria, you can retrieve entries based on size, + time, and attributes. See for a + description of the syntax of the SelectionCriteria string. + + + + + The ZipFile from which to retrieve entries. + + + the directory in the archive from which to select entries. If null, then + all directories in the archive are used. + + + a collection of ZipEntry objects that conform to the criteria. + + + + Summary description for EnumUtil. + + + + + Returns the value of the DescriptionAttribute if the specified Enum + value has one. If not, returns the ToString() representation of the + Enum value. + + The Enum to get the description for + + + + + Converts the string representation of the name or numeric value of one + or more enumerated constants to an equivalent enumerated object. + Note: use the DescriptionAttribute on enum values to enable this. + + The System.Type of the enumeration. + + A string containing the name or value to convert. + + + + + + Converts the string representation of the name or numeric value of one + or more enumerated constants to an equivalent enumerated object. A + parameter specified whether the operation is case-sensitive. Note: + use the DescriptionAttribute on enum values to enable this. + + The System.Type of the enumeration. + + A string containing the name or value to convert. + + + Whether the operation is case-sensitive or not. + + + + + 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. + + + + + Indicates the total number of bytes applied to the CRC. + + + + + Indicates the current CRC for all blocks slurped in. + + + + + Returns the CRC32 for the specified stream. + + The stream over which to calculate the CRC32 + the CRC32 calculation + + + + 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 + + + + 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. + + + + 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 + + + + Process one byte in the CRC. + + the byte to include into the CRC . + + + + 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. + + + + 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 + + + + Create an instance of the CRC32 class using the default settings: no + bit reversal, and a polynomial of 0xEDB88320. + + + + + 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. + + + + + + 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. + + + + + + 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. + + + + + + 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. + + + + + + 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 + + + + 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. + + + + 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 + + + + 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. + + + + 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 + + + + 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. + + + + + 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. + + + + + + Indicates whether the underlying stream will be left open when the + CrcCalculatorStream is Closed. + + + + Set this at any point before calling . + + + + + + 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 + + + + Write to the stream. + + the buffer from which to write + the offset at which to start writing + the number of bytes to write + + + + Indicates whether the stream supports reading. + + + + + Indicates whether the stream supports seeking. + + + + Always returns false. + + + + + + Indicates whether the stream supports writing. + + + + + Flush the stream. + + + + + Returns the length of the underlying stream. + + + + + The getter for this property returns the total bytes read. + If you use the setter, it will throw + . + + + + + Seeking is not supported on this stream. This method always throws + + + N/A + N/A + N/A + + + + This method always throws + + + N/A + + + + Closes the stream. + + + + + 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. + + + + + + + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + This property sets the flush behavior on the stream. + + See the ZLIB documentation for the meaning of the flush behavior. + + + + + 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. + + + + + + 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. + + + + Returns the total number of bytes input so far. + + + Returns the total number of bytes output so far. + + + + 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. + + + + + Indicates whether the stream can be read. + + + The return value depends on whether the captive stream supports reading. + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream can be written. + + + The return value depends on whether the captive stream supports writing. + + + + + Flush the stream. + + + + + Reading this property always throws a . + + + + + 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. + + + + + 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 + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + this is irrelevant, since it will always throw! + irrelevant! + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + + + + 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. + + + + 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 + + + + 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 + + + + 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 + + + + 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 + + + + 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. + + + + + + + + + + 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). + + + + + + 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). + + + + + + 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(). + + + + + The CRC on the GZIP stream. + + + This is used for internal error checking. You probably don't need to look at this property. + + + + + 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. + + + + 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. + + + + 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. + + + + + 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. + + + + This property sets the flush behavior on the stream. + + + + + 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. + + + + + Returns the total number of bytes input so far. + + + Returns the total number of bytes output so far. + + + + 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. + + + + + Indicates whether the stream can be read. + + + The return value depends on whether the captive stream supports reading. + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream can be written. + + + The return value depends on whether the captive stream supports writing. + + + + + Flush the stream. + + + + + Reading this property always throws a . + + + + + 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. + + + + + 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 + + + + Calling this method always throws a . + + irrelevant; it will always throw! + irrelevant; it will always throw! + irrelevant! + + + + Calling this method always throws a . + + irrelevant; this method will always throw! + + + + 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. + + + + 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 + + + + Compress a byte array into a new byte array using GZip. + + + + Uncompress it with . + + + + + + + A buffer to compress. + + + The data in compressed form + + + + Uncompress a GZip'ed byte array into a single string. + + + + + + + A buffer containing GZIP-compressed data. + + + The uncompressed string + + + + 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 + + + + A class for compressing streams using the + Deflate algorithm with multiple threads. + + + + + This class performs DEFLATE compression through writing. For + more information on the Deflate algorithm, see IETF RFC 1951, + "DEFLATE Compressed Data Format Specification version 1.3." + + + + This class is similar to , except + that this class is for compression only, and this implementation uses an + approach that employs multiple worker threads to perform the DEFLATE. On + a multi-cpu or multi-core computer, the performance of this class can be + significantly higher than the single-threaded DeflateStream, particularly + for larger streams. How large? Anything over 10mb is a good candidate + for parallel compression. + + + + The tradeoff is that this class uses more memory and more CPU than the + vanilla DeflateStream, and also is less efficient as a compressor. For + large files the size of the compressed data stream can be less than 1% + larger than the size of a compressed data stream from the vanialla + DeflateStream. For smaller files the difference can be larger. The + difference will also be larger if you set the BufferSize to be lower than + the default value. Your mileage may vary. Finally, for small files, the + ParallelDeflateOutputStream can be much slower than the vanilla + DeflateStream, because of the overhead associated to using the thread + pool. + + + + + + + + Create a ParallelDeflateOutputStream. + + + + + This stream compresses data written into it via the DEFLATE + algorithm (see RFC 1951), and writes out the compressed byte stream. + + + + The instance will use the default compression level, the default + buffer sizes and the default number of threads and buffers per + thread. + + + + This class is similar to , + except that this implementation uses an approach that employs + multiple worker threads to perform the DEFLATE. On a multi-cpu or + multi-core computer, the performance of this class can be + significantly higher than the single-threaded DeflateStream, + particularly for larger streams. How large? Anything over 10mb is + a good candidate for parallel compression. + + + + + + + This example shows how to use a ParallelDeflateOutputStream to compress + data. It reads a file, compresses it, and writes the compressed data to + a second, output file. + + + byte[] buffer = new byte[WORKING_BUFFER_SIZE]; + int n= -1; + String outputFile = fileToCompress + ".compressed"; + using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) + { + using (var raw = System.IO.File.Create(outputFile)) + { + using (Stream compressor = new ParallelDeflateOutputStream(raw)) + { + while ((n= input.Read(buffer, 0, buffer.Length)) != 0) + { + compressor.Write(buffer, 0, n); + } + } + } + } + + + Dim buffer As Byte() = New Byte(4096) {} + Dim n As Integer = -1 + Dim outputFile As String = (fileToCompress & ".compressed") + Using input As Stream = File.OpenRead(fileToCompress) + Using raw As FileStream = File.Create(outputFile) + Using compressor As Stream = New ParallelDeflateOutputStream(raw) + Do While (n <> 0) + If (n > 0) Then + compressor.Write(buffer, 0, n) + End If + n = input.Read(buffer, 0, buffer.Length) + Loop + End Using + End Using + End Using + + + The stream to which compressed data will be written. + + + + Create a ParallelDeflateOutputStream using the specified CompressionLevel. + + + See the + constructor for example code. + + The stream to which compressed data will be written. + A tuning knob to trade speed for effectiveness. + + + + Create a ParallelDeflateOutputStream and specify whether to leave the captive stream open + when the ParallelDeflateOutputStream is closed. + + + See the + constructor for example code. + + The stream to which compressed data will be written. + + true if the application would like the stream to remain open after inflation/deflation. + + + + + Create a ParallelDeflateOutputStream and specify whether to leave the captive stream open + when the ParallelDeflateOutputStream is closed. + + + See the + constructor for example code. + + The stream to which compressed data will be written. + A tuning knob to trade speed for effectiveness. + + true if the application would like the stream to remain open after inflation/deflation. + + + + + Create a ParallelDeflateOutputStream using the specified + CompressionLevel and CompressionStrategy, and specifying whether to + leave the captive stream open when the ParallelDeflateOutputStream is + closed. + + + See the + constructor for example code. + + The stream to which compressed data will be written. + A tuning knob to trade speed for effectiveness. + + By tweaking this parameter, you may be able to optimize the compression for + data with particular characteristics. + + + true if the application would like the stream to remain open after inflation/deflation. + + + + + The ZLIB strategy to be used during compression. + + + + + + The maximum number of buffer pairs to use. + + + + + This property sets an upper limit on the number of memory buffer + pairs to create. The implementation of this stream allocates + multiple buffers to facilitate parallel compression. As each buffer + fills up, this stream uses + ThreadPool.QueueUserWorkItem() + to compress those buffers in a background threadpool thread. After a + buffer is compressed, it is re-ordered and written to the output + stream. + + + + A higher number of buffer pairs enables a higher degree of + parallelism, which tends to increase the speed of compression on + multi-cpu computers. On the other hand, a higher number of buffer + pairs also implies a larger memory consumption, more active worker + threads, and a higher cpu utilization for any compression. This + property enables the application to limit its memory consumption and + CPU utilization behavior depending on requirements. + + + + For each compression "task" that occurs in parallel, there are 2 + buffers allocated: one for input and one for output. This property + sets a limit for the number of pairs. The total amount of storage + space allocated for buffering will then be (N*S*2), where N is the + number of buffer pairs, S is the size of each buffer (). By default, DotNetZip allocates 4 buffer + pairs per CPU core, so if your machine has 4 cores, and you retain + the default buffer size of 128k, then the + ParallelDeflateOutputStream will use 4 * 4 * 2 * 128kb of buffer + memory in total, or 4mb, in blocks of 128kb. If you then set this + property to 8, then the number will be 8 * 2 * 128kb of buffer + memory, or 2mb. + + + + CPU utilization will also go up with additional buffers, because a + larger number of buffer pairs allows a larger number of background + threads to compress in parallel. If you find that parallel + compression is consuming too much memory or CPU, you can adjust this + value downward. + + + + The default value is 16. Different values may deliver better or + worse results, depending on your priorities and the dynamic + performance characteristics of your storage and compute resources. + + + + This property is not the number of buffer pairs to use; it is an + upper limit. An illustration: Suppose you have an application that + uses the default value of this property (which is 16), and it runs + on a machine with 2 CPU cores. In that case, DotNetZip will allocate + 4 buffer pairs per CPU core, for a total of 8 pairs. The upper + limit specified by this property has no effect. + + + + The application can set this value at any time, but it is effective + only before the first call to Write(), which is when the buffers are + allocated. + + + + + + The size of the buffers used by the compressor threads. + + + + + The default buffer size is 128k. The application can set this value + at any time, but it is effective only before the first Write(). + + + + Larger buffer sizes implies larger memory consumption but allows + more efficient compression. Using smaller buffer sizes consumes less + memory but may result in less effective compression. For example, + using the default buffer size of 128k, the compression delivered is + within 1% of the compression delivered by the single-threaded . On the other hand, using a + BufferSize of 8k can result in a compressed data stream that is 5% + larger than that delivered by the single-threaded + DeflateStream. Excessively small buffer sizes can also cause + the speed of the ParallelDeflateOutputStream to drop, because of + larger thread scheduling overhead dealing with many many small + buffers. + + + + The total amount of storage space allocated for buffering will be + (N*S*2), where N is the number of buffer pairs, and S is the size of + each buffer (this property). There are 2 buffers used by the + compressor, one for input and one for output. By default, DotNetZip + allocates 4 buffer pairs per CPU core, so if your machine has 4 + cores, then the number of buffer pairs used will be 16. If you + accept the default value of this property, 128k, then the + ParallelDeflateOutputStream will use 16 * 2 * 128kb of buffer memory + in total, or 4mb, in blocks of 128kb. If you set this property to + 64kb, then the number will be 16 * 2 * 64kb of buffer memory, or + 2mb. + + + + + + + The CRC32 for the data that was written out, prior to compression. + + + This value is meaningful only after a call to Close(). + + + + + The total number of uncompressed bytes processed by the ParallelDeflateOutputStream. + + + This value is meaningful only after a call to Close(). + + + + + Write data to the stream. + + + + + + To use the ParallelDeflateOutputStream to compress data, create a + ParallelDeflateOutputStream with CompressionMode.Compress, passing a + writable output stream. Then call Write() on that + ParallelDeflateOutputStream, providing uncompressed data as input. The + data sent to the output stream will be the compressed form of the data + written. + + + + To decompress data, use the class. + + + + The buffer holding data to write to the stream. + the offset within that data array to find the first byte to write. + the number of bytes to write. + + + + Flush the stream. + + + + + Close the stream. + + + You must call Close on the stream to guarantee that all of the data written in has + been compressed, and the compressed data has been written out. + + + + Dispose the object + + + Because ParallelDeflateOutputStream is IDisposable, the + application must call this method when finished using the instance. + + + This method is generally called implicitly upon exit from + a using scope in C# (Using in VB). + + + + + The Dispose method + + indicates whether the Dispose method was invoked by user code. + + + + + Resets the stream for use with another stream. + + + Because the ParallelDeflateOutputStream is expensive to create, it + has been designed so that it can be recycled and re-used. You have + to call Close() on the stream first, then you can call Reset() on + it, to use it again on another stream. + + + + The new output stream for this era. + + + + + ParallelDeflateOutputStream deflater = null; + foreach (var inputFile in listOfFiles) + { + string outputFile = inputFile + ".compressed"; + using (System.IO.Stream input = System.IO.File.OpenRead(inputFile)) + { + using (var outStream = System.IO.File.Create(outputFile)) + { + if (deflater == null) + deflater = new ParallelDeflateOutputStream(outStream, + CompressionLevel.Best, + CompressionStrategy.Default, + true); + deflater.Reset(outStream); + + while ((n= input.Read(buffer, 0, buffer.Length)) != 0) + { + deflater.Write(buffer, 0, n); + } + } + } + } + + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream supports Read operations. + + + Always returns false. + + + + + Indicates whether the stream supports Write operations. + + + Returns true if the provided stream is writable. + + + + + Reading this property always throws a NotSupportedException. + + + + + Returns the current position of the output stream. + + + + Because the output gets written by a background thread, + the value may change asynchronously. Setting this + property always throws a NotSupportedException. + + + + + + This method always throws a NotSupportedException. + + + The buffer into which data would be read, IF THIS METHOD + ACTUALLY DID ANYTHING. + + + The offset within that data array at which to insert the + data that is read, IF THIS METHOD ACTUALLY DID + ANYTHING. + + + The number of bytes to write, IF THIS METHOD ACTUALLY DID + ANYTHING. + + nothing. + + + + This method always throws a NotSupportedException. + + + The offset to seek to.... + IF THIS METHOD ACTUALLY DID ANYTHING. + + + The reference specifying how to apply the offset.... IF + THIS METHOD ACTUALLY DID ANYTHING. + + nothing. It always throws. + + + + This method always throws a NotSupportedException. + + + The new value for the stream length.... IF + THIS METHOD ACTUALLY DID ANYTHING. + + + + + Map from a distance to a distance code. + + + No side effects. _dist_code[256] and _dist_code[257] are never used. + + + + + Describes how to flush the current deflate operation. + + + The different FlushType values are useful when using a Deflate in a streaming application. + + + + No flush at all. + + + 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. + + + + + 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. + + + + + 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. + + + + Signals the end of the compression/decompression stream. + + + + The compression level to be used when using a DeflateStream or ZlibStream with CompressionMode.Compress. + + + + + 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. + + + + + Same as None. + + + + + The fastest but least effective compression. + + + + + A synonym for BestSpeed. + + + + + A little slower, but better, than level 1. + + + + + A little slower, but better, than level 2. + + + + + A little slower, but better, than level 3. + + + + + A little slower than level 4, but with better compression. + + + + + The default compression level, with a good balance of speed and compression efficiency. + + + + + A synonym for Default. + + + + + Pretty good compression! + + + + + Better compression than Level7! + + + + + The "best" compression, where best means greatest reduction in size of the input data stream. + This is also the slowest compression. + + + + + A synonym for BestCompression. + + + + + 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. + + + + + The default strategy is probably the best for normal data. + + + + + 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. + + + + + Using HuffmanOnly will force the compressor to do Huffman encoding only, with no + string matching. + + + + + An enum to specify the direction of transcoding - whether to compress or decompress. + + + + + Used to specify that the stream should compress the data. + + + + + Used to specify that the stream should decompress the data. + + + + + A general purpose exception class for exceptions in the Zlib library. + + + + + The ZlibException class captures exception information generated + by the Zlib library. + + + + + This ctor collects a message attached to the exception. + + the message for the exception. + + + + 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 + + + + 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. + + + + + 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. + + + + + + + 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); + + + + + + 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. + + + + + The buffer from which data is taken. + + + + + An index into the InputBuffer array, indicating where to start reading. + + + + + 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. + + + + + Total number of bytes read so far, through all calls to Inflate()/Deflate(). + + + + + Buffer to store output data. + + + + + An index into the OutputBuffer array, indicating where to start writing. + + + + + 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. + + + + + Total number of bytes written to the output so far, through all calls to Inflate()/Deflate(). + + + + + used for diagnostics, when something goes wrong! + + + + + The compression level to use in this codec. Useful only in compression mode. + + + + + 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. + + + + + 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. + + + + + The Adler32 checksum on the data transferred through the codec so far. You probably don't need to look at this. + + + + + 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. + + + + + Create a ZlibCodec that either compresses or decompresses. + + + Indicates whether the codec should compress (deflate) or decompress (inflate). + + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + I don't know what this does! + + Z_OK if everything goes well. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + Set the dictionary to be used for either Inflation or Deflation. + + The dictionary bytes to use. + Z_OK if all goes well. + + + + Set the dictionary to be used for either Inflation or Deflation unconditionally. + + Decoding a MSZip file requires the dictionary state to be set unconditionally + at the end of each block to the previous decoded data + The dictionary bytes to use. + Z_OK if all goes well. + + + + A bunch of constants used in the Zlib interface. + + + + + The maximum number of window bits for the Deflate algorithm. + + + + + The default number of window bits for the Deflate algorithm. + + + + + indicates everything is A-OK + + + + + Indicates that the last operation reached the end of the stream. + + + + + The operation ended in need of a dictionary. + + + + + There was an error with the stream - not enough data, not open and readable, etc. + + + + + There was an error with the data - not enough data, bad data, etc. + + + + + There was an error with the working buffer. + + + + + The size of the working buffer used in the ZlibCodec class. + + + + + The minimum size of the working buffer used in the ZlibCodec class. + + + + + 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 + . + + + + + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + + This property sets the flush behavior on the stream. + Sorry, though, not sure exactly how to describe all the various settings. + + + + + 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. + + + + + Returns the total number of bytes input so far. + + + Returns the total number of bytes output so far. + + + + 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. + + + + + Indicates whether the stream can be read. + + + The return value depends on whether the captive stream supports reading. + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream can be written. + + + The return value depends on whether the captive stream supports writing. + + + + + Flush the stream. + + + + + Reading this property always throws a . + + + + + 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. + + + + + 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 + + + + 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. + + + + Calling this method always throws a . + + + The new value for the stream length.... IF + THIS METHOD ACTUALLY DID ANYTHING. + + + + + 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. + + + + 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 + + + + Compress a byte array into a new byte array using ZLIB. + + + + Uncompress it with . + + + + + + + A buffer to compress. + + + The data in compressed form + + + + Uncompress a ZLIB-compressed byte array into a single string. + + + + + + + A buffer containing ZLIB-compressed data. + + + The uncompressed string + + + + Uncompress a ZLIB-compressed byte array into a byte array. + + + + + + + A buffer containing ZLIB-compressed data. + + + The data in uncompressed form + +
+
diff --git a/packages/DotNetZip.1.13.4/lib/netstandard2.0/DotNetZip.dll b/packages/DotNetZip.1.13.4/lib/netstandard2.0/DotNetZip.dll new file mode 100644 index 0000000..2c6088a Binary files /dev/null and b/packages/DotNetZip.1.13.4/lib/netstandard2.0/DotNetZip.dll differ diff --git a/packages/DotNetZip.1.13.4/lib/netstandard2.0/DotNetZip.pdb b/packages/DotNetZip.1.13.4/lib/netstandard2.0/DotNetZip.pdb new file mode 100644 index 0000000..a4f5522 Binary files /dev/null and b/packages/DotNetZip.1.13.4/lib/netstandard2.0/DotNetZip.pdb differ diff --git a/packages/DotNetZip.1.13.4/lib/netstandard2.0/DotNetZip.xml b/packages/DotNetZip.1.13.4/lib/netstandard2.0/DotNetZip.xml new file mode 100644 index 0000000..e1f7c2e --- /dev/null +++ b/packages/DotNetZip.1.13.4/lib/netstandard2.0/DotNetZip.xml @@ -0,0 +1,18031 @@ + + + + DotNetZip + + + + + Delivers the remaining bits, left-aligned, in a byte. + + + + This is valid only if NumRemainingBits is less than 8; + in other words it is valid only after a call to Flush(). + + + + + + Reset the BitWriter. + + + + This is useful when the BitWriter writes into a MemoryStream, and + is used by a BZip2Compressor, which itself is re-used for multiple + distinct data blocks. + + + + + + Write some number of bits from the given value, into the output. + + + + The nbits value should be a max of 25, for safety. For performance + reasons, this method does not check! + + + + + + Write a full 8-bit byte into the output. + + + + + Write four 8-bit bytes into the output. + + + + + Write all available byte-aligned bytes. + + + + This method writes no new output, but flushes any accumulated + bits. At completion, the accumulator may contain up to 7 + bits. + + + This is necessary when re-assembling output from N independent + compressors, one for each of N blocks. The output of any + particular compressor will in general have some fragment of a byte + remaining. This fragment needs to be accumulated into the + parent BZip2OutputStream. + + + + + + Writes all available bytes, and emits padding for the final byte as + necessary. This must be the last method invoked on an instance of + BitWriter. + + + + Knuth's increments seem to work better than Incerpi-Sedgewick here. + Possibly because the number of elems to sort is usually small, typically + <= 20. + + + + BZip2Compressor writes its compressed data out via a BitWriter. This + is necessary because BZip2 does byte shredding. + + + + + The number of uncompressed bytes being held in the buffer. + + + + I am thinking this may be useful in a Stream that uses this + compressor class. In the Close() method on the stream it could + check this value to see if anything has been written at all. You + may think the stream could easily track the number of bytes it + wrote, which would eliminate the need for this. But, there is the + case where the stream writes a complete block, and it is full, and + then writes no more. In that case the stream may want to check. + + + + + + Accept new bytes into the compressor data buffer + + + + This method does the first-level (cheap) run-length encoding, and + stores the encoded data into the rle block. + + + + + + Process one input byte into the block. + + + + + To "process" the byte means to do the run-length encoding. + There are 3 possible return values: + + 0 - the byte was not written, in other words, not + encoded into the block. This happens when the + byte b would require the start of a new run, and + the block has no more room for new runs. + + 1 - the byte was written, and the block is not full. + + 2 - the byte was written, and the block is full. + + + + 0 if the byte was not written, non-zero if written. + + + + Append one run to the output block. + + + + + This compressor does run-length-encoding before BWT and etc. This + method simply appends a run to the output block. The append always + succeeds. The return value indicates whether the block is full: + false (not full) implies that at least one additional run could be + processed. + + + true if the block is now full; otherwise false. + + + + Compress the data that has been placed (Run-length-encoded) into the + block. The compressed data goes into the CompressedBytes array. + + + + Side effects: 1. fills the CompressedBytes array. 2. sets the + AvailableBytesOut property. + + + + + This is the most hammered method of this class. + +

+ This is the version using unrolled loops. +

+
+ + Method "mainQSort3", file "blocksort.c", BZip2 1.0.2 + + + Array instance identical to sfmap, both are used only + temporarily and independently, so we do not need to allocate + additional memory. + + + + A read-only decorator stream that performs BZip2 decompression on Read. + + + + + Compressor State + + + + + Create a BZip2InputStream, wrapping it around the given input Stream. + + + + The input stream will be closed when the BZip2InputStream is closed. + + + The stream from which to read compressed data + + + + Create a BZip2InputStream with the given stream, and + specifying whether to leave the wrapped stream open when + the BZip2InputStream is closed. + + The stream from which to read compressed data + + Whether to leave the input stream open, when the BZip2InputStream closes. + + + + + This example reads a bzip2-compressed file, decompresses it, + and writes the decompressed data into a newly created file. + + + var fname = "logfile.log.bz2"; + using (var fs = File.OpenRead(fname)) + { + using (var decompressor = new Ionic.BZip2.BZip2InputStream(fs)) + { + var outFname = fname + ".decompressed"; + using (var output = File.Create(outFname)) + { + byte[] buffer = new byte[2048]; + int n; + while ((n = decompressor.Read(buffer, 0, buffer.Length)) > 0) + { + output.Write(buffer, 0, n); + } + } + } + } + + + + + + Read data from the stream. + + + + + To decompress a BZip2 data stream, create a BZip2InputStream, + providing a stream that reads compressed data. Then call Read() on + that BZip2InputStream, and the data read will be decompressed + as you read. + + + + A BZip2InputStream can be used only for Read(), not for Write(). + + + + 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 + + + + Read a single byte from the stream. + + the byte read from the stream, or -1 if EOF + + + + Indicates whether the stream can be read. + + + The return value depends on whether the captive stream supports reading. + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream can be written. + + + The return value depends on whether the captive stream supports writing. + + + + + Flush the stream. + + + + + Reading this property always throws a . + + + + + The position of the stream pointer. + + + + Setting this property always throws a . Reading will return the + total number of uncompressed bytes read in. + + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + this is irrelevant, since it will always throw! + irrelevant! + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + + + + Calling this method always throws a . + + this parameter is never used + this parameter is never used + this parameter is never used + + + + Dispose the stream. + + + indicates whether the Dispose method was invoked by user code. + + + + + Close the stream. + + + + + Read n bits from input, right justifying the result. + + + + For example, if you read 1 bit, the result is either 0 + or 1. + + + + The number of bits to read, always between 1 and 32. + + + + Called by createHuffmanDecodingTables() exclusively. + + + Called by recvDecodingTables() exclusively. + + + Freq table collected to save a pass over the data during + decompression. + + + Initializes the tt array. + + This method is called when the required length of the array is known. + I don't initialize it at construction time to avoid unneccessary + memory allocation when compressing small files. + + + + A write-only decorator stream that compresses data as it is + written using the BZip2 algorithm. + + + + + Constructs a new BZip2OutputStream, that sends its + compressed output to the given output stream. + + + + The destination stream, to which compressed output will be sent. + + + + + This example reads a file, then compresses it with bzip2 file, + and writes the compressed data into a newly created file. + + + var fname = "logfile.log"; + using (var fs = File.OpenRead(fname)) + { + var outFname = fname + ".bz2"; + using (var output = File.Create(outFname)) + { + using (var compressor = new Ionic.BZip2.BZip2OutputStream(output)) + { + byte[] buffer = new byte[2048]; + int n; + while ((n = fs.Read(buffer, 0, buffer.Length)) > 0) + { + compressor.Write(buffer, 0, n); + } + } + } + } + + + + + + Constructs a new BZip2OutputStream with specified blocksize. + + the destination stream. + + The blockSize in units of 100000 bytes. + The valid range is 1..9. + + + + + Constructs a new BZip2OutputStream. + + the destination stream. + + whether to leave the captive stream open upon closing this stream. + + + + + Constructs a new BZip2OutputStream with specified blocksize, + and explicitly specifies whether to leave the wrapped stream open. + + + the destination stream. + + The blockSize in units of 100000 bytes. + The valid range is 1..9. + + + whether to leave the captive stream open upon closing this stream. + + + + + Close the stream. + + + + This may or may not close the underlying stream. Check the + constructors that accept a bool value. + + + + + + Flush the stream. + + + + + The blocksize parameter specified at construction time. + + + + + Write data to the stream. + + + + + Use the BZip2OutputStream to compress data while writing: + create a BZip2OutputStream with a writable output stream. + Then call Write() on that BZip2OutputStream, providing + uncompressed data as input. The data sent to the output stream will + be the compressed form of the input data. + + + + A BZip2OutputStream can be used only for Write() not for Read(). + + + + + 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. + + + + Indicates whether the stream can be read. + + + The return value is always false. + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream can be written. + + + The return value should always be true, unless and until the + object is disposed and closed. + + + + + Reading this property always throws a . + + + + + The position of the stream pointer. + + + + Setting this property always throws a . Reading will return the + total number of uncompressed bytes written through. + + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + this is irrelevant, since it will always throw! + irrelevant! + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + + + + Calling this method always throws a . + + this parameter is never used + this parameter is never used + this parameter is never used + never returns anything; always throws + + + + A write-only decorator stream that compresses data as it is + written using the BZip2 algorithm. This stream compresses by + block using multiple threads. + + + This class performs BZIP2 compression through writing. For + more information on the BZIP2 algorithm, see + . + + + + This class is similar to , + except that this implementation uses an approach that employs multiple + worker threads to perform the compression. On a multi-cpu or multi-core + computer, the performance of this class can be significantly higher than + the single-threaded BZip2OutputStream, particularly for larger streams. + How large? Anything over 10mb is a good candidate for parallel + compression. + + + + The tradeoff is that this class uses more memory and more CPU than the + vanilla BZip2OutputStream. Also, for small files, the + ParallelBZip2OutputStream can be much slower than the vanilla + BZip2OutputStream, because of the overhead associated to using the + thread pool. + + + + + + + Constructs a new ParallelBZip2OutputStream, that sends its + compressed output to the given output stream. + + + + The destination stream, to which compressed output will be sent. + + + + + This example reads a file, then compresses it with bzip2 file, + and writes the compressed data into a newly created file. + + + var fname = "logfile.log"; + using (var fs = File.OpenRead(fname)) + { + var outFname = fname + ".bz2"; + using (var output = File.Create(outFname)) + { + using (var compressor = new Ionic.BZip2.ParallelBZip2OutputStream(output)) + { + byte[] buffer = new byte[2048]; + int n; + while ((n = fs.Read(buffer, 0, buffer.Length)) > 0) + { + compressor.Write(buffer, 0, n); + } + } + } + } + + + + + + Constructs a new ParallelBZip2OutputStream with specified blocksize. + + the destination stream. + + The blockSize in units of 100000 bytes. + The valid range is 1..9. + + + + + Constructs a new ParallelBZip2OutputStream. + + the destination stream. + + whether to leave the captive stream open upon closing this stream. + + + + + Constructs a new ParallelBZip2OutputStream with specified blocksize, + and explicitly specifies whether to leave the wrapped stream open. + + + the destination stream. + + The blockSize in units of 100000 bytes. + The valid range is 1..9. + + + whether to leave the captive stream open upon closing this stream. + + + + + The maximum number of concurrent compression worker threads to use. + + + + + This property sets an upper limit on the number of concurrent worker + threads to employ for compression. The implementation of this stream + employs multiple threads from the .NET thread pool, via + ThreadPool.QueueUserWorkItem(), to compress the incoming data by + block. As each block of data is compressed, this stream re-orders the + compressed blocks and writes them to the output stream. + + + + A higher number of workers enables a higher degree of + parallelism, which tends to increase the speed of compression on + multi-cpu computers. On the other hand, a higher number of buffer + pairs also implies a larger memory consumption, more active worker + threads, and a higher cpu utilization for any compression. This + property enables the application to limit its memory consumption and + CPU utilization behavior depending on requirements. + + + + By default, DotNetZip allocates 4 workers per CPU core, subject to the + upper limit specified in this property. For example, suppose the + application sets this property to 16. Then, on a machine with 2 + cores, DotNetZip will use 8 workers; that number does not exceed the + upper limit specified by this property, so the actual number of + workers used will be 4 * 2 = 8. On a machine with 4 cores, DotNetZip + will use 16 workers; again, the limit does not apply. On a machine + with 8 cores, DotNetZip will use 16 workers, because of the limit. + + + + For each compression "worker thread" that occurs in parallel, there is + up to 2mb of memory allocated, for buffering and processing. The + actual number depends on the property. + + + + CPU utilization will also go up with additional workers, because a + larger number of buffer pairs allows a larger number of background + threads to compress in parallel. If you find that parallel + compression is consuming too much memory or CPU, you can adjust this + value downward. + + + + The default value is 16. Different values may deliver better or + worse results, depending on your priorities and the dynamic + performance characteristics of your storage and compute resources. + + + + The application can set this value at any time, but it is effective + only before the first call to Write(), which is when the buffers are + allocated. + + + + + + Close the stream. + + + + This may or may not close the underlying stream. Check the + constructors that accept a bool value. + + + + + + Flush the stream. + + + + + The blocksize parameter specified at construction time. + + + + + Write data to the stream. + + + + + Use the ParallelBZip2OutputStream to compress data while + writing: create a ParallelBZip2OutputStream with a writable + output stream. Then call Write() on that + ParallelBZip2OutputStream, providing uncompressed data as + input. The data sent to the output stream will be the compressed + form of the input data. + + + + A ParallelBZip2OutputStream can be used only for + Write() not for Read(). + + + + + 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. + + + + Indicates whether the stream can be read. + + + The return value is always false. + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream can be written. + + + The return value depends on whether the captive stream supports writing. + + + + + Reading this property always throws a . + + + + + The position of the stream pointer. + + + + Setting this property always throws a . Reading will return the + total number of uncompressed bytes written through. + + + + + The total number of bytes written out by the stream. + + + This value is meaningful only after a call to Close(). + + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + this is irrelevant, since it will always throw! + irrelevant! + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + + + + Calling this method always throws a . + + this parameter is never used + this parameter is never used + this parameter is never used + never returns anything; always throws + + + + Returns the "random" number at a specific index. + + the index + the random number + + + + 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. + + + + + Indicates the total number of bytes applied to the CRC. + + + + + Indicates the current CRC for all blocks slurped in. + + + + + Returns the CRC32 for the specified stream. + + The stream over which to calculate the CRC32 + the CRC32 calculation + + + + 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 + + + + 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. + + + + 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 + + + + Process one byte in the CRC. + + the byte to include into the CRC . + + + + 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. + + + + 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 + + + + Create an instance of the CRC32 class using the default settings: no + bit reversal, and a polynomial of 0xEDB88320. + + + + + 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. + + + + + + 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. + + + + + + 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. + + + + + + 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. + + + + + + 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 + + + + 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. + + + + 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 + + + + 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. + + + + 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 + + + + 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. + + + + + 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. + + + + + + Indicates whether the underlying stream will be left open when the + CrcCalculatorStream is Closed. + + + + Set this at any point before calling . + + + + + + 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 + + + + Write to the stream. + + the buffer from which to write + the offset at which to start writing + the number of bytes to write + + + + Indicates whether the stream supports reading. + + + + + Indicates whether the stream supports seeking. + + + + Always returns false. + + + + + + Indicates whether the stream supports writing. + + + + + Flush the stream. + + + + + Returns the length of the underlying stream. + + + + + The getter for this property returns the total bytes read. + If you use the setter, it will throw + . + + + + + Seeking is not supported on this stream. This method always throws + + + N/A + N/A + N/A + + + + This method always throws + + + N/A + + + + Closes the stream. + + + + + 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. + + + + + + + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + This property sets the flush behavior on the stream. + + See the ZLIB documentation for the meaning of the flush behavior. + + + + + 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. + + + + + + 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. + + + + Returns the total number of bytes input so far. + + + Returns the total number of bytes output so far. + + + + 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. + + + + + Indicates whether the stream can be read. + + + The return value depends on whether the captive stream supports reading. + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream can be written. + + + The return value depends on whether the captive stream supports writing. + + + + + Flush the stream. + + + + + Reading this property always throws a . + + + + + 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. + + + + + 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 + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + this is irrelevant, since it will always throw! + irrelevant! + + + + Calling this method always throws a . + + this is irrelevant, since it will always throw! + + + + 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. + + + + 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 + + + + 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 + + + + 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 + + + + 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 + + + + 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. + + + + + + + + + + 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). + + + + + + 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). + + + + + + 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(). + + + + + The CRC on the GZIP stream. + + + This is used for internal error checking. You probably don't need to look at this property. + + + + + 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. + + + + 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. + + + + 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. + + + + + 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. + + + + This property sets the flush behavior on the stream. + + + + + 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. + + + + + Returns the total number of bytes input so far. + + + Returns the total number of bytes output so far. + + + + 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. + + + + + Indicates whether the stream can be read. + + + The return value depends on whether the captive stream supports reading. + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream can be written. + + + The return value depends on whether the captive stream supports writing. + + + + + Flush the stream. + + + + + Reading this property always throws a . + + + + + 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. + + + + + 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 + + + + Calling this method always throws a . + + irrelevant; it will always throw! + irrelevant; it will always throw! + irrelevant! + + + + Calling this method always throws a . + + irrelevant; this method will always throw! + + + + 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. + + + + 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 + + + + Compress a byte array into a new byte array using GZip. + + + + Uncompress it with . + + + + + + + A buffer to compress. + + + The data in compressed form + + + + Uncompress a GZip'ed byte array into a single string. + + + + + + + A buffer containing GZIP-compressed data. + + + The uncompressed string + + + + 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 + + + + A class for compressing streams using the + Deflate algorithm with multiple threads. + + + + + This class performs DEFLATE compression through writing. For + more information on the Deflate algorithm, see IETF RFC 1951, + "DEFLATE Compressed Data Format Specification version 1.3." + + + + This class is similar to , except + that this class is for compression only, and this implementation uses an + approach that employs multiple worker threads to perform the DEFLATE. On + a multi-cpu or multi-core computer, the performance of this class can be + significantly higher than the single-threaded DeflateStream, particularly + for larger streams. How large? Anything over 10mb is a good candidate + for parallel compression. + + + + The tradeoff is that this class uses more memory and more CPU than the + vanilla DeflateStream, and also is less efficient as a compressor. For + large files the size of the compressed data stream can be less than 1% + larger than the size of a compressed data stream from the vanialla + DeflateStream. For smaller files the difference can be larger. The + difference will also be larger if you set the BufferSize to be lower than + the default value. Your mileage may vary. Finally, for small files, the + ParallelDeflateOutputStream can be much slower than the vanilla + DeflateStream, because of the overhead associated to using the thread + pool. + + + + + + + + Create a ParallelDeflateOutputStream. + + + + + This stream compresses data written into it via the DEFLATE + algorithm (see RFC 1951), and writes out the compressed byte stream. + + + + The instance will use the default compression level, the default + buffer sizes and the default number of threads and buffers per + thread. + + + + This class is similar to , + except that this implementation uses an approach that employs + multiple worker threads to perform the DEFLATE. On a multi-cpu or + multi-core computer, the performance of this class can be + significantly higher than the single-threaded DeflateStream, + particularly for larger streams. How large? Anything over 10mb is + a good candidate for parallel compression. + + + + + + + This example shows how to use a ParallelDeflateOutputStream to compress + data. It reads a file, compresses it, and writes the compressed data to + a second, output file. + + + byte[] buffer = new byte[WORKING_BUFFER_SIZE]; + int n= -1; + String outputFile = fileToCompress + ".compressed"; + using (System.IO.Stream input = System.IO.File.OpenRead(fileToCompress)) + { + using (var raw = System.IO.File.Create(outputFile)) + { + using (Stream compressor = new ParallelDeflateOutputStream(raw)) + { + while ((n= input.Read(buffer, 0, buffer.Length)) != 0) + { + compressor.Write(buffer, 0, n); + } + } + } + } + + + Dim buffer As Byte() = New Byte(4096) {} + Dim n As Integer = -1 + Dim outputFile As String = (fileToCompress & ".compressed") + Using input As Stream = File.OpenRead(fileToCompress) + Using raw As FileStream = File.Create(outputFile) + Using compressor As Stream = New ParallelDeflateOutputStream(raw) + Do While (n <> 0) + If (n > 0) Then + compressor.Write(buffer, 0, n) + End If + n = input.Read(buffer, 0, buffer.Length) + Loop + End Using + End Using + End Using + + + The stream to which compressed data will be written. + + + + Create a ParallelDeflateOutputStream using the specified CompressionLevel. + + + See the + constructor for example code. + + The stream to which compressed data will be written. + A tuning knob to trade speed for effectiveness. + + + + Create a ParallelDeflateOutputStream and specify whether to leave the captive stream open + when the ParallelDeflateOutputStream is closed. + + + See the + constructor for example code. + + The stream to which compressed data will be written. + + true if the application would like the stream to remain open after inflation/deflation. + + + + + Create a ParallelDeflateOutputStream and specify whether to leave the captive stream open + when the ParallelDeflateOutputStream is closed. + + + See the + constructor for example code. + + The stream to which compressed data will be written. + A tuning knob to trade speed for effectiveness. + + true if the application would like the stream to remain open after inflation/deflation. + + + + + Create a ParallelDeflateOutputStream using the specified + CompressionLevel and CompressionStrategy, and specifying whether to + leave the captive stream open when the ParallelDeflateOutputStream is + closed. + + + See the + constructor for example code. + + The stream to which compressed data will be written. + A tuning knob to trade speed for effectiveness. + + By tweaking this parameter, you may be able to optimize the compression for + data with particular characteristics. + + + true if the application would like the stream to remain open after inflation/deflation. + + + + + The ZLIB strategy to be used during compression. + + + + + + The maximum number of buffer pairs to use. + + + + + This property sets an upper limit on the number of memory buffer + pairs to create. The implementation of this stream allocates + multiple buffers to facilitate parallel compression. As each buffer + fills up, this stream uses + ThreadPool.QueueUserWorkItem() + to compress those buffers in a background threadpool thread. After a + buffer is compressed, it is re-ordered and written to the output + stream. + + + + A higher number of buffer pairs enables a higher degree of + parallelism, which tends to increase the speed of compression on + multi-cpu computers. On the other hand, a higher number of buffer + pairs also implies a larger memory consumption, more active worker + threads, and a higher cpu utilization for any compression. This + property enables the application to limit its memory consumption and + CPU utilization behavior depending on requirements. + + + + For each compression "task" that occurs in parallel, there are 2 + buffers allocated: one for input and one for output. This property + sets a limit for the number of pairs. The total amount of storage + space allocated for buffering will then be (N*S*2), where N is the + number of buffer pairs, S is the size of each buffer (). By default, DotNetZip allocates 4 buffer + pairs per CPU core, so if your machine has 4 cores, and you retain + the default buffer size of 128k, then the + ParallelDeflateOutputStream will use 4 * 4 * 2 * 128kb of buffer + memory in total, or 4mb, in blocks of 128kb. If you then set this + property to 8, then the number will be 8 * 2 * 128kb of buffer + memory, or 2mb. + + + + CPU utilization will also go up with additional buffers, because a + larger number of buffer pairs allows a larger number of background + threads to compress in parallel. If you find that parallel + compression is consuming too much memory or CPU, you can adjust this + value downward. + + + + The default value is 16. Different values may deliver better or + worse results, depending on your priorities and the dynamic + performance characteristics of your storage and compute resources. + + + + This property is not the number of buffer pairs to use; it is an + upper limit. An illustration: Suppose you have an application that + uses the default value of this property (which is 16), and it runs + on a machine with 2 CPU cores. In that case, DotNetZip will allocate + 4 buffer pairs per CPU core, for a total of 8 pairs. The upper + limit specified by this property has no effect. + + + + The application can set this value at any time, but it is effective + only before the first call to Write(), which is when the buffers are + allocated. + + + + + + The size of the buffers used by the compressor threads. + + + + + The default buffer size is 128k. The application can set this value + at any time, but it is effective only before the first Write(). + + + + Larger buffer sizes implies larger memory consumption but allows + more efficient compression. Using smaller buffer sizes consumes less + memory but may result in less effective compression. For example, + using the default buffer size of 128k, the compression delivered is + within 1% of the compression delivered by the single-threaded . On the other hand, using a + BufferSize of 8k can result in a compressed data stream that is 5% + larger than that delivered by the single-threaded + DeflateStream. Excessively small buffer sizes can also cause + the speed of the ParallelDeflateOutputStream to drop, because of + larger thread scheduling overhead dealing with many many small + buffers. + + + + The total amount of storage space allocated for buffering will be + (N*S*2), where N is the number of buffer pairs, and S is the size of + each buffer (this property). There are 2 buffers used by the + compressor, one for input and one for output. By default, DotNetZip + allocates 4 buffer pairs per CPU core, so if your machine has 4 + cores, then the number of buffer pairs used will be 16. If you + accept the default value of this property, 128k, then the + ParallelDeflateOutputStream will use 16 * 2 * 128kb of buffer memory + in total, or 4mb, in blocks of 128kb. If you set this property to + 64kb, then the number will be 16 * 2 * 64kb of buffer memory, or + 2mb. + + + + + + + The CRC32 for the data that was written out, prior to compression. + + + This value is meaningful only after a call to Close(). + + + + + The total number of uncompressed bytes processed by the ParallelDeflateOutputStream. + + + This value is meaningful only after a call to Close(). + + + + + Write data to the stream. + + + + + + To use the ParallelDeflateOutputStream to compress data, create a + ParallelDeflateOutputStream with CompressionMode.Compress, passing a + writable output stream. Then call Write() on that + ParallelDeflateOutputStream, providing uncompressed data as input. The + data sent to the output stream will be the compressed form of the data + written. + + + + To decompress data, use the class. + + + + The buffer holding data to write to the stream. + the offset within that data array to find the first byte to write. + the number of bytes to write. + + + + Flush the stream. + + + + + Close the stream. + + + You must call Close on the stream to guarantee that all of the data written in has + been compressed, and the compressed data has been written out. + + + + Dispose the object + + + Because ParallelDeflateOutputStream is IDisposable, the + application must call this method when finished using the instance. + + + This method is generally called implicitly upon exit from + a using scope in C# (Using in VB). + + + + + The Dispose method + + indicates whether the Dispose method was invoked by user code. + + + + + Resets the stream for use with another stream. + + + Because the ParallelDeflateOutputStream is expensive to create, it + has been designed so that it can be recycled and re-used. You have + to call Close() on the stream first, then you can call Reset() on + it, to use it again on another stream. + + + + The new output stream for this era. + + + + + ParallelDeflateOutputStream deflater = null; + foreach (var inputFile in listOfFiles) + { + string outputFile = inputFile + ".compressed"; + using (System.IO.Stream input = System.IO.File.OpenRead(inputFile)) + { + using (var outStream = System.IO.File.Create(outputFile)) + { + if (deflater == null) + deflater = new ParallelDeflateOutputStream(outStream, + CompressionLevel.Best, + CompressionStrategy.Default, + true); + deflater.Reset(outStream); + + while ((n= input.Read(buffer, 0, buffer.Length)) != 0) + { + deflater.Write(buffer, 0, n); + } + } + } + } + + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream supports Read operations. + + + Always returns false. + + + + + Indicates whether the stream supports Write operations. + + + Returns true if the provided stream is writable. + + + + + Reading this property always throws a NotSupportedException. + + + + + Returns the current position of the output stream. + + + + Because the output gets written by a background thread, + the value may change asynchronously. Setting this + property always throws a NotSupportedException. + + + + + + This method always throws a NotSupportedException. + + + The buffer into which data would be read, IF THIS METHOD + ACTUALLY DID ANYTHING. + + + The offset within that data array at which to insert the + data that is read, IF THIS METHOD ACTUALLY DID + ANYTHING. + + + The number of bytes to write, IF THIS METHOD ACTUALLY DID + ANYTHING. + + nothing. + + + + This method always throws a NotSupportedException. + + + The offset to seek to.... + IF THIS METHOD ACTUALLY DID ANYTHING. + + + The reference specifying how to apply the offset.... IF + THIS METHOD ACTUALLY DID ANYTHING. + + nothing. It always throws. + + + + This method always throws a NotSupportedException. + + + The new value for the stream length.... IF + THIS METHOD ACTUALLY DID ANYTHING. + + + + + Map from a distance to a distance code. + + + No side effects. _dist_code[256] and _dist_code[257] are never used. + + + + + Describes how to flush the current deflate operation. + + + The different FlushType values are useful when using a Deflate in a streaming application. + + + + No flush at all. + + + 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. + + + + + 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. + + + + + 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. + + + + Signals the end of the compression/decompression stream. + + + + The compression level to be used when using a DeflateStream or ZlibStream with CompressionMode.Compress. + + + + + 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. + + + + + Same as None. + + + + + The fastest but least effective compression. + + + + + A synonym for BestSpeed. + + + + + A little slower, but better, than level 1. + + + + + A little slower, but better, than level 2. + + + + + A little slower, but better, than level 3. + + + + + A little slower than level 4, but with better compression. + + + + + The default compression level, with a good balance of speed and compression efficiency. + + + + + A synonym for Default. + + + + + Pretty good compression! + + + + + Better compression than Level7! + + + + + The "best" compression, where best means greatest reduction in size of the input data stream. + This is also the slowest compression. + + + + + A synonym for BestCompression. + + + + + 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. + + + + + The default strategy is probably the best for normal data. + + + + + 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. + + + + + Using HuffmanOnly will force the compressor to do Huffman encoding only, with no + string matching. + + + + + An enum to specify the direction of transcoding - whether to compress or decompress. + + + + + Used to specify that the stream should compress the data. + + + + + Used to specify that the stream should decompress the data. + + + + + A general purpose exception class for exceptions in the Zlib library. + + + + + The ZlibException class captures exception information generated + by the Zlib library. + + + + + This ctor collects a message attached to the exception. + + the message for the exception. + + + + 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 + + + + 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. + + + + + 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. + + + + + + + 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); + + + + + + 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. + + + + + The buffer from which data is taken. + + + + + An index into the InputBuffer array, indicating where to start reading. + + + + + 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. + + + + + Total number of bytes read so far, through all calls to Inflate()/Deflate(). + + + + + Buffer to store output data. + + + + + An index into the OutputBuffer array, indicating where to start writing. + + + + + 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. + + + + + Total number of bytes written to the output so far, through all calls to Inflate()/Deflate(). + + + + + used for diagnostics, when something goes wrong! + + + + + The compression level to use in this codec. Useful only in compression mode. + + + + + 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. + + + + + 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. + + + + + The Adler32 checksum on the data transferred through the codec so far. You probably don't need to look at this. + + + + + 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. + + + + + Create a ZlibCodec that either compresses or decompresses. + + + Indicates whether the codec should compress (deflate) or decompress (inflate). + + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + I don't know what this does! + + Z_OK if everything goes well. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + Set the dictionary to be used for either Inflation or Deflation. + + The dictionary bytes to use. + Z_OK if all goes well. + + + + Set the dictionary to be used for either Inflation or Deflation unconditionally. + + Decoding a MSZip file requires the dictionary state to be set unconditionally + at the end of each block to the previous decoded data + The dictionary bytes to use. + Z_OK if all goes well. + + + + A bunch of constants used in the Zlib interface. + + + + + The maximum number of window bits for the Deflate algorithm. + + + + + The default number of window bits for the Deflate algorithm. + + + + + indicates everything is A-OK + + + + + Indicates that the last operation reached the end of the stream. + + + + + The operation ended in need of a dictionary. + + + + + There was an error with the stream - not enough data, not open and readable, etc. + + + + + There was an error with the data - not enough data, bad data, etc. + + + + + There was an error with the working buffer. + + + + + The size of the working buffer used in the ZlibCodec class. + + + + + The minimum size of the working buffer used in the ZlibCodec class. + + + + + 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 + . + + + + + + + + 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. + + + + 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. + + + + 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. + + + + 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. + + + + + This property sets the flush behavior on the stream. + Sorry, though, not sure exactly how to describe all the various settings. + + + + + 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. + + + + + Returns the total number of bytes input so far. + + + Returns the total number of bytes output so far. + + + + 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. + + + + + Indicates whether the stream can be read. + + + The return value depends on whether the captive stream supports reading. + + + + + Indicates whether the stream supports Seek operations. + + + Always returns false. + + + + + Indicates whether the stream can be written. + + + The return value depends on whether the captive stream supports writing. + + + + + Flush the stream. + + + + + Reading this property always throws a . + + + + + 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. + + + + + 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 + + + + 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. + + + + Calling this method always throws a . + + + The new value for the stream length.... IF + THIS METHOD ACTUALLY DID ANYTHING. + + + + + 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. + + + + 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 + + + + Compress a byte array into a new byte array using ZLIB. + + + + Uncompress it with . + + + + + + + A buffer to compress. + + + The data in compressed form + + + + Uncompress a ZLIB-compressed byte array into a single string. + + + + + + + A buffer containing ZLIB-compressed data. + + + The uncompressed string + + + + Uncompress a ZLIB-compressed byte array into a byte array. + + + + + + + A buffer containing ZLIB-compressed data. + + + The data in uncompressed form + + + + This class exposes a set of COM-accessible wrappers for static + methods available on the ZipFile class. You don't need this + class unless you are using DotNetZip from a COM environment. + + + + + A wrapper for ZipFile.IsZipFile(string) + + The filename to of the zip file to check. + true if the file contains a valid zip file. + + + + A wrapper for ZipFile.IsZipFile(string, bool) + + + We cannot use "overloaded" Method names in COM interop. + So, here, we use a unique name. + + The filename to of the zip file to check. + true if the file contains a valid zip file. + + + + A wrapper for ZipFile.CheckZip(string) + + The filename to of the zip file to check. + + true if the named zip file checks OK. Otherwise, false. + + + + A COM-friendly wrapper for the static method . + + + The filename to of the zip file to check. + + The password to check. + + true if the named zip file checks OK. Otherwise, false. + + + + A wrapper for ZipFile.FixZipDirectory(string) + + The filename to of the zip file to fix. + + + + A wrapper for ZipFile.LibraryVersion + + + the version number on the DotNetZip assembly, formatted as a string. + + + + + An enum that provides the various encryption algorithms supported by this + library. + + + + + + PkzipWeak implies the use of Zip 2.0 encryption, which is known to be + weak and subvertible. + + + + A note on interoperability: Values of PkzipWeak and None are + specified in PKWARE's zip + specification, and are considered to be "standard". Zip archives + produced using these options will be interoperable with many other zip tools + and libraries, including Windows Explorer. + + + + Values of WinZipAes128 and WinZipAes256 are not part of the Zip + specification, but rather imply the use of a vendor-specific extension from + WinZip. If you want to produce interoperable Zip archives, do not use these + values. For example, if you produce a zip archive using WinZipAes256, you + will be able to open it in Windows Explorer on Windows XP and Vista, but you + will not be able to extract entries; trying this will lead to an "unspecified + error". For this reason, some people have said that a zip archive that uses + WinZip's AES encryption is not actually a zip archive at all. A zip archive + produced this way will be readable with the WinZip tool (Version 11 and + beyond). + + + + There are other third-party tools and libraries, both commercial and + otherwise, that support WinZip's AES encryption. These will be able to read + AES-encrypted zip archives produced by DotNetZip, and conversely applications + that use DotNetZip to read zip archives will be able to read AES-encrypted + archives produced by those tools or libraries. Consult the documentation for + those other tools and libraries to find out if WinZip's AES encryption is + supported. + + + + In case you care: According to the WinZip specification, the + actual AES key used is derived from the via an + algorithm that complies with RFC 2898, using an iteration + count of 1000. The algorithm is sometimes referred to as PBKDF2, which stands + for "Password Based Key Derivation Function #2". + + + + A word about password strength and length: The AES encryption technology is + very good, but any system is only as secure as the weakest link. If you want + to secure your data, be sure to use a password that is hard to guess. To make + it harder to guess (increase its "entropy"), you should make it longer. If + you use normal characters from an ASCII keyboard, a password of length 20 will + be strong enough that it will be impossible to guess. For more information on + that, I'd encourage you to read this + article. + + + + + + + No encryption at all. + + + + + Traditional or Classic pkzip encryption. + + + + + WinZip AES encryption (128 key bits). + + + + + WinZip AES encryption (256 key bits). + + + + + An encryption algorithm that is not supported by DotNetZip. + + + + + Delegate in which the application writes the ZipEntry content for the named entry. + + + The name of the entry that must be written. + The stream to which the entry data should be written. + + + When you add an entry and specify a WriteDelegate, via , the application + code provides the logic that writes the entry data directly into the zip file. + + + + + This example shows how to define a WriteDelegate that obtains a DataSet, and then + writes the XML for the DataSet into the zip archive. There's no need to + save the XML to a disk file first. + + + private void WriteEntry (String filename, Stream output) + { + DataSet ds1 = ObtainDataSet(); + ds1.WriteXml(output); + } + + private void Run() + { + using (var zip = new ZipFile()) + { + zip.AddEntry(zipEntryName, WriteEntry); + zip.Save(zipFileName); + } + } + + + + Private Sub WriteEntry (ByVal filename As String, ByVal output As Stream) + DataSet ds1 = ObtainDataSet() + ds1.WriteXml(stream) + End Sub + + Public Sub Run() + Using zip = New ZipFile + zip.AddEntry(zipEntryName, New WriteDelegate(AddressOf WriteEntry)) + zip.Save(zipFileName) + End Using + End Sub + + + + + + + Delegate in which the application opens the stream, just-in-time, for the named entry. + + + + The name of the ZipEntry that the application should open the stream for. + + + + When you add an entry via , the application code provides the logic that + opens and closes the stream for the given ZipEntry. + + + + + + + Delegate in which the application closes the stream, just-in-time, for the named entry. + + + + The name of the ZipEntry that the application should close the stream for. + + + The stream to be closed. + + + When you add an entry via , the application code provides the logic that + opens and closes the stream for the given ZipEntry. + + + + + + + Delegate for the callback by which the application tells the + library the CompressionLevel to use for a file. + + + + + Using this callback, the application can, for example, specify that + previously-compressed files (.mp3, .png, .docx, etc) should use a + CompressionLevel of None, or can set the compression level based + on any other factor. + + + + + + + In an EventArgs type, indicates which sort of progress event is being + reported. + + + There are events for reading, events for saving, and events for + extracting. This enumeration allows a single EventArgs type to be sued to + describe one of multiple subevents. For example, a SaveProgress event is + invoked before, after, and during the saving of a single entry. The value + of an enum with this type, specifies which event is being triggered. The + same applies to Extraction, Reading and Adding events. + + + + + Indicates that a Add() operation has started. + + + + + Indicates that an individual entry in the archive has been added. + + + + + Indicates that a Add() operation has completed. + + + + + Indicates that a Read() operation has started. + + + + + Indicates that an individual entry in the archive is about to be read. + + + + + Indicates that an individual entry in the archive has just been read. + + + + + Indicates that a Read() operation has completed. + + + + + The given event reports the number of bytes read so far + during a Read() operation. + + + + + Indicates that a Save() operation has started. + + + + + Indicates that an individual entry in the archive is about to be written. + + + + + Indicates that an individual entry in the archive has just been saved. + + + + + Indicates that a Save() operation has completed. + + + + + Indicates that the zip archive has been created in a + temporary location during a Save() operation. + + + + + Indicates that the temporary file is about to be renamed to the final archive + name during a Save() operation. + + + + + Indicates that the temporary file is has just been renamed to the final archive + name during a Save() operation. + + + + + Indicates that the self-extracting archive has been compiled + during a Save() operation. + + + + + The given event is reporting the number of source bytes that have run through the compressor so far + during a Save() operation. + + + + + Indicates that an entry is about to be extracted. + + + + + Indicates that an entry has just been extracted. + + + + + Indicates that extraction of an entry would overwrite an existing + filesystem file. You must use + + ExtractExistingFileAction.InvokeExtractProgressEvent in the call + to ZipEntry.Extract() in order to receive this event. + + + + + The given event is reporting the number of bytes written so far for + the current entry during an Extract() operation. + + + + + Indicates that an ExtractAll operation is about to begin. + + + + + Indicates that an ExtractAll operation has completed. + + + + + Indicates that an error has occurred while saving a zip file. + This generally means the file cannot be opened, because it has been + removed, or because it is locked by another process. It can also + mean that the file cannot be Read, because of a range lock conflict. + + + + + Provides information about the progress of a save, read, or extract operation. + This is a base class; you will probably use one of the classes derived from this one. + + + + + The total number of entries to be saved or extracted. + + + + + The name of the last entry saved or extracted. + + + + + In an event handler, set this to cancel the save or extract + operation that is in progress. + + + + + The type of event being reported. + + + + + Returns the archive name associated to this event. + + + + + The number of bytes read or written so far for this entry. + + + + + Total number of bytes that will be read or written for this entry. + This number will be -1 if the value cannot be determined. + + + + + Provides information about the progress of a Read operation. + + + + + Provides information about the progress of a Add operation. + + + + + Provides information about the progress of a save operation. + + + + + Constructor for the SaveProgressEventArgs. + + the name of the zip archive. + whether this is before saving the entry, or after + The total number of entries in the zip archive. + Number of entries that have been saved. + The entry involved in the event. + + + + Number of entries saved so far. + + + + + Provides information about the progress of the extract operation. + + + + + Constructor for the ExtractProgressEventArgs. + + the name of the zip archive. + whether this is before saving the entry, or after + The total number of entries in the zip archive. + Number of entries that have been extracted. + The entry involved in the event. + The location to which entries are extracted. + + + + Number of entries extracted so far. This is set only if the + EventType is Extracting_BeforeExtractEntry or Extracting_AfterExtractEntry, and + the Extract() is occurring witin the scope of a call to ExtractAll(). + + + + + Returns the extraction target location, a filesystem path. + + + + + Provides information about the an error that occurred while zipping. + + + + + Returns the exception that occurred, if any. + + + + + Returns the name of the file that caused the exception, if any. + + + + + Issued when an ZipEntry.ExtractWithPassword() method is invoked + with an incorrect password. + + + + + Default ctor. + + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + The innerException for this exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The serialization info for the exception. + The streaming context from which to deserialize. + + + + Indicates that a read was attempted on a stream, and bad or incomplete data was + received. + + + + + Default ctor. + + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + The innerException for this exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The serialization info for the exception. + The streaming context from which to deserialize. + + + + Issued when an CRC check fails upon extracting an entry from a zip archive. + + + + + Default ctor. + + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The serialization info for the exception. + The streaming context from which to deserialize. + + + + Issued when errors occur saving a self-extracting archive. + + + + + Default ctor. + + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The serialization info for the exception. + The streaming context from which to deserialize. + + + + Indicates that an operation was attempted on a ZipFile which was not possible + given the state of the instance. For example, if you call Save() on a ZipFile + which has no filename set, you can get this exception. + + + + + Default ctor. + + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + The innerException for this exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The serialization info for the exception. + The streaming context from which to deserialize. + + + + Base class for all exceptions defined by and throw by the Zip library. + + + + + Default ctor. + + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The message in the exception. + The innerException for this exception. + + + + Come on, you know how exceptions work. Why are you looking at this documentation? + + The serialization info for the exception. + The streaming context from which to deserialize. + + + + An enum for the options when extracting an entry would overwrite an existing file. + + + + + This enum describes the actions that the library can take when an + Extract() or ExtractWithPassword() method is called to extract an + entry to a filesystem, and the extraction would overwrite an existing filesystem + file. + + + + + + + Throw an exception when extraction would overwrite an existing file. (For + COM clients, this is a 0 (zero).) + + + + + When extraction would overwrite an existing file, overwrite the file silently. + The overwrite will happen even if the target file is marked as read-only. + (For COM clients, this is a 1.) + + + + + When extraction would overwrite an existing file, don't overwrite the file, silently. + (For COM clients, this is a 2.) + + + + + When extraction would overwrite an existing file, invoke the ExtractProgress + event, using an event type of . In + this way, the application can decide, just-in-time, whether to overwrite the + file. For example, a GUI application may wish to pop up a dialog to allow + the user to choose. You may want to examine the property before making + the decision. If, after your processing in the Extract progress event, you + want to NOT extract the file, set + on the ZipProgressEventArgs.CurrentEntry to DoNotOverwrite. + If you do want to extract the file, set ZipEntry.ExtractExistingFile + to OverwriteSilently. If you want to cancel the Extraction, set + ZipProgressEventArgs.Cancel to true. Cancelling differs from using + DoNotOverwrite in that a cancel will not extract any further entries, if + there are any. (For COM clients, the value of this enum is a 3.) + + + + + Collects general purpose utility methods. + + + + private null constructor + + + + Utility routine for transforming path names from filesystem format (on Windows that means backslashes) to + a format suitable for use within zipfiles. This means trimming the volume letter and colon (if any) And + swapping backslashes for forward slashes. + + source path. + transformed path + + + + Sanitize paths in zip files. This means making sure that relative paths in a zip file don't go outside + the top directory. Entries like something/../../../../Temp/evil.txt get sanitized to Temp/evil.txt + when extracting + + A path with forward slashes as directory separator + sanitized path + + + + Finds a signature in the zip stream. This is useful for finding + the end of a zip entry, for example, or the beginning of the next ZipEntry. + + + + + Scans through 64k at a time. + + + + If the method fails to find the requested signature, the stream Position + after completion of this method is unchanged. If the method succeeds in + finding the requested signature, the stream position after completion is + direct AFTER the signature found in the stream. + + + + The stream to search + The 4-byte signature to find + The number of bytes read + + + + Create a pseudo-random filename, suitable for use as a temporary + file, and open it. + + + + This method produces a filename of the form + DotNetZip-xxxxxxxx.tmp, where xxxxxxxx is replaced by randomly + chosen characters, and creates that file. + + + + + + Workitem 7889: handle ERROR_LOCK_VIOLATION during read + + + This could be gracefully handled with an extension attribute, but + This assembly used to be built for .NET 2.0, so could not use + extension methods. + + + + + A decorator stream. It wraps another stream, and performs bookkeeping + to keep track of the stream Position. + + + + In some cases, it is not possible to get the Position of a stream, let's + say, on a write-only output stream like ASP.NET's + Response.OutputStream, or on a different write-only stream + provided as the destination for the zip by the application. In this + case, programmers can use this counting stream to count the bytes read + or written. + + + Consider the scenario of an application that saves a self-extracting + archive (SFX), that uses a custom SFX stub. + + + Saving to a filesystem file, the application would open the + filesystem file (getting a FileStream), save the custom sfx stub + into it, and then call ZipFile.Save(), specifying the same + FileStream. ZipFile.Save() does the right thing for the zipentry + offsets, by inquiring the Position of the FileStream before writing + any data, and then adding that initial offset into any ZipEntry + offsets in the zip directory. Everything works fine. + + + Now suppose the application is an ASPNET application and it saves + directly to Response.OutputStream. It's not possible for DotNetZip to + inquire the Position, so the offsets for the SFX will be wrong. + + + The workaround is for the application to use this class to wrap + HttpResponse.OutputStream, then write the SFX stub and the ZipFile + into that wrapper stream. Because ZipFile.Save() can inquire the + Position, it will then do the right thing with the offsets. + + + + + + The constructor. + + The underlying stream + + + + Gets the wrapped stream. + + + + + The count of bytes written out to the stream. + + + + + the count of bytes that have been read from the stream. + + + + + Adjust the byte count on the stream. + + + + the number of bytes to subtract from the count. + + + + + Subtract delta from the count of bytes written to the stream. + This is necessary when seeking back, and writing additional data, + as happens in some cases when saving Zip files. + + + + + + The read method. + + The buffer to hold the data read from the stream. + the offset within the buffer to copy the first byte read. + the number of bytes to read. + the number of bytes read, after decryption and decompression. + + + + Write data into the stream. + + The buffer holding data to write to the stream. + the offset within that data array to find the first byte to write. + the number of bytes to write. + + + + Whether the stream can be read. + + + + + Whether it is possible to call Seek() on the stream. + + + + + Whether it is possible to call Write() on the stream. + + + + + Flushes the underlying stream. + + + + + The length of the underlying stream. + + + + + Returns the sum of number of bytes written, plus the initial + offset before writing. + + + + + The Position of the stream. + + + + + Seek in the stream. + + the offset point to seek to + the reference point from which to seek + The new position + + + + Set the length of the underlying stream. Be careful with this! + + + the length to set on the underlying stream. + + + + This is a helper class supporting WinZip AES encryption. + This class is intended for use only by the DotNetZip library. + + + + Most uses of the DotNetZip library will not involve direct calls into + the WinZipAesCrypto class. Instead, the WinZipAesCrypto class is + instantiated and used by the ZipEntry() class when WinZip AES + encryption or decryption on an entry is employed. + + + + + A stream that encrypts as it writes, or decrypts as it reads. The + Crypto is AES in CTR (counter) mode, which is compatible with the AES + encryption employed by WinZip 12.0. + + + + The AES/CTR encryption protocol used by WinZip works like this: + + - start with a counter, initialized to zero. + + - to encrypt, take the data by 16-byte blocks. For each block: + - apply the transform to the counter + - increement the counter + - XOR the result of the transform with the plaintext to + get the ciphertext. + - compute the mac on the encrypted bytes + - when finished with all blocks, store the computed MAC. + + - to decrypt, take the data by 16-byte blocks. For each block: + - compute the mac on the encrypted bytes, + - apply the transform to the counter + - increement the counter + - XOR the result of the transform with the ciphertext to + get the plaintext. + - when finished with all blocks, compare the computed MAC against + the stored MAC + + + + + + + The constructor. + + The underlying stream + To either encrypt or decrypt. + The pre-initialized WinZipAesCrypto object. + The maximum number of bytes to read from the stream. + + + + Returns the final HMAC-SHA1-80 for the data that was encrypted. + + + + + Close the stream. + + + + + Returns true if the stream can be read. + + + + + Always returns false. + + + + + Returns true if the CryptoMode is Encrypt. + + + + + Flush the content in the stream. + + + + + Getting this property throws a NotImplementedException. + + + + + Getting or Setting this property throws a NotImplementedException. + + + + + This method throws a NotImplementedException. + + + + + This method throws a NotImplementedException. + + + + + This class implements the "traditional" or "classic" PKZip encryption, + which today is considered to be weak. On the other hand it is + ubiquitous. This class is intended for use only by the DotNetZip + library. + + + + Most uses of the DotNetZip library will not involve direct calls into + the ZipCrypto class. Instead, the ZipCrypto class is instantiated and + used by the ZipEntry() class when encryption or decryption on an entry + is employed. If for some reason you really wanted to use a weak + encryption algorithm in some other application, you might use this + library. But you would be much better off using one of the built-in + strong encryption libraries in the .NET Framework, like the AES + algorithm or SHA. + + + + + The default constructor for ZipCrypto. + + + + This class is intended for internal use by the library only. It's + probably not useful to you. Seriously. Stop reading this + documentation. It's a waste of your time. Go do something else. + Check the football scores. Go get an ice cream with a friend. + Seriously. + + + + + + From AppNote.txt: + unsigned char decrypt_byte() + local unsigned short temp + temp :=- Key(2) | 2 + decrypt_byte := (temp * (temp ^ 1)) bitshift-right 8 + end decrypt_byte + + + + + Call this method on a cipher text to render the plaintext. You must + first initialize the cipher with a call to InitCipher. + + + + + var cipher = new ZipCrypto(); + cipher.InitCipher(Password); + // Decrypt the header. This has a side effect of "further initializing the + // encryption keys" in the traditional zip encryption. + byte[] DecryptedMessage = cipher.DecryptMessage(EncryptedMessage); + + + + The encrypted buffer. + + The number of bytes to encrypt. + Should be less than or equal to CipherText.Length. + + + The plaintext. + + + + This is the converse of DecryptMessage. It encrypts the plaintext + and produces a ciphertext. + + + The plain text buffer. + + + The number of bytes to encrypt. + Should be less than or equal to plainText.Length. + + + The ciphertext. + + + + This initializes the cipher with the given password. + See AppNote.txt for details. + + + + The passphrase for encrypting or decrypting with this cipher. + + + + + Step 1 - Initializing the encryption keys + ----------------------------------------- + Start with these keys: + Key(0) := 305419896 (0x12345678) + Key(1) := 591751049 (0x23456789) + Key(2) := 878082192 (0x34567890) + + Then, initialize the keys with a password: + + loop for i from 0 to length(password)-1 + update_keys(password(i)) + end loop + + Where update_keys() is defined as: + + update_keys(char): + Key(0) := crc32(key(0),char) + Key(1) := Key(1) + (Key(0) bitwiseAND 000000ffH) + Key(1) := Key(1) * 134775813 + 1 + Key(2) := crc32(key(2),key(1) rightshift 24) + end update_keys + + Where crc32(old_crc,char) is a routine that given a CRC value and a + character, returns an updated CRC value after applying the CRC-32 + algorithm described elsewhere in this document. + + + + + After the keys are initialized, then you can use the cipher to + encrypt the plaintext. + + + + Essentially we encrypt the password with the keys, then discard the + ciphertext for the password. This initializes the keys for later use. + + + + + + + A Stream for reading and concurrently decrypting data from a zip file, + or for writing and concurrently encrypting data to a zip file. + + + + The constructor. + The underlying stream + To either encrypt or decrypt. + The pre-initialized ZipCrypto object. + + + + Represents a single entry in a ZipFile. Typically, applications get a ZipEntry + by enumerating the entries within a ZipFile, or by adding an entry to a ZipFile. + + + + + True if the referenced entry is a directory. + + + + + Provides a human-readable string with information about the ZipEntry. + + + + + Reads one entry from the zip directory structure in the zip file. + + + + The zipfile for which a directory entry will be read. From this param, the + method gets the ReadStream and the expected text encoding + (ProvisionalAlternateEncoding) which is used if the entry is not marked + UTF-8. + + + + a list of previously seen entry names; used to prevent duplicates. + + + the entry read from the archive. + + + + Returns true if the passed-in value is a valid signature for a ZipDirEntry. + + the candidate 4-byte signature value. + true, if the signature is valid according to the PKWare spec. + + + + Default constructor. + + + Applications should never need to call this directly. It is exposed to + support COM Automation environments. + + + + + The time and date at which the file indicated by the ZipEntry was + last modified. + + + + + The DotNetZip library sets the LastModified value for an entry, equal to + the Last Modified time of the file in the filesystem. If an entry is + added from a stream, the library uses System.DateTime.Now for this + value, for the given entry. + + + + This property allows the application to retrieve and possibly set the + LastModified value on an entry, to an arbitrary value. values with a + setting of DateTimeKind.Unspecified are taken to be expressed as + DateTimeKind.Local. + + + + Be aware that because of the way PKWare's + Zip specification describes how times are stored in the zip file, + the full precision of the System.DateTime datatype is not stored + for the last modified time when saving zip files. For more information on + how times are formatted, see the PKZip specification. + + + + The actual last modified time of a file can be stored in multiple ways in + the zip file, and they are not mutually exclusive: + + + + + In the so-called "DOS" format, which has a 2-second precision. Values + are rounded to the nearest even second. For example, if the time on the + file is 12:34:43, then it will be stored as 12:34:44. This first value + is accessible via the LastModified property. This value is always + present in the metadata for each zip entry. In some cases the value is + invalid, or zero. + + + + In the so-called "Windows" or "NTFS" format, as an 8-byte integer + quantity expressed as the number of 1/10 milliseconds (in other words + the number of 100 nanosecond units) since January 1, 1601 (UTC). This + format is how Windows represents file times. This time is accessible + via the ModifiedTime property. + + + + In the "Unix" format, a 4-byte quantity specifying the number of seconds since + January 1, 1970 UTC. + + + + In an older format, now deprecated but still used by some current + tools. This format is also a 4-byte quantity specifying the number of + seconds since January 1, 1970 UTC. + + + + + + Zip tools and libraries will always at least handle (read or write) the + DOS time, and may also handle the other time formats. Keep in mind that + while the names refer to particular operating systems, there is nothing in + the time formats themselves that prevents their use on other operating + systems. + + + + When reading ZIP files, the DotNetZip library reads the Windows-formatted + time, if it is stored in the entry, and sets both LastModified and + ModifiedTime to that value. When writing ZIP files, the DotNetZip + library by default will write both time quantities. It can also emit the + Unix-formatted time if desired (See .) + + + + The last modified time of the file created upon a call to + ZipEntry.Extract() may be adjusted during extraction to compensate + for differences in how the .NET Base Class Library deals with daylight + saving time (DST) versus how the Windows filesystem deals with daylight + saving time. Raymond Chen provides + some good context. + + + + In a nutshell: Daylight savings time rules change regularly. In 2007, for + example, the inception week of DST changed. In 1977, DST was in place all + year round. In 1945, likewise. And so on. Win32 does not attempt to + guess which time zone rules were in effect at the time in question. It + will render a time as "standard time" and allow the app to change to DST + as necessary. .NET makes a different choice. + + + + Compare the output of FileInfo.LastWriteTime.ToString("f") with what you + see in the Windows Explorer property sheet for a file that was last + written to on the other side of the DST transition. For example, suppose + the file was last modified on October 17, 2003, during DST but DST is not + currently in effect. Explorer's file properties reports Thursday, October + 17, 2003, 8:45:38 AM, but .NETs FileInfo reports Thursday, October 17, + 2003, 9:45 AM. + + + + Win32 says, "Thursday, October 17, 2002 8:45:38 AM PST". Note: Pacific + STANDARD Time. Even though October 17 of that year occurred during Pacific + Daylight Time, Win32 displays the time as standard time because that's + what time it is NOW. + + + + .NET BCL assumes that the current DST rules were in place at the time in + question. So, .NET says, "Well, if the rules in effect now were also in + effect on October 17, 2003, then that would be daylight time" so it + displays "Thursday, October 17, 2003, 9:45 AM PDT" - daylight time. + + + + So .NET gives a value which is more intuitively correct, but is also + potentially incorrect, and which is not invertible. Win32 gives a value + which is intuitively incorrect, but is strictly correct. + + + + Because of this funkiness, this library adds one hour to the LastModified + time on the extracted file, if necessary. That is to say, if the time in + question had occurred in what the .NET Base Class Library assumed to be + DST. This assumption may be wrong given the constantly changing DST rules, + but it is the best we can do. + + + + + + + + Ability to set Last Modified DOS time to zero + (for using with EmitTimesInWindowsFormatWhenSaving+EmitTimesInUnixFormatWhenSaving setted to false) + some flasher hardware use as marker of first binary + + + + + Last Modified time for the file represented by the entry. + + + + + + This value corresponds to the "last modified" time in the NTFS file times + as described in the Zip + specification. When getting this property, the value may be + different from . When setting the property, + the property also gets set, but with a lower + precision. + + + + Let me explain. It's going to take a while, so get + comfortable. Originally, waaaaay back in 1989 when the ZIP specification + was originally described by the esteemed Mr. Phil Katz, the dominant + operating system of the time was MS-DOS. MSDOS stored file times with a + 2-second precision, because, c'mon, who is ever going to need better + resolution than THAT? And so ZIP files, regardless of the platform on + which the zip file was created, store file times in exactly the same format that DOS used + in 1989. + + + + Since then, the ZIP spec has evolved, but the internal format for file + timestamps remains the same. Despite the fact that the way times are + stored in a zip file is rooted in DOS heritage, any program on any + operating system can format a time in this way, and most zip tools and + libraries DO - they round file times to the nearest even second and store + it just like DOS did 25+ years ago. + + + + PKWare extended the ZIP specification to allow a zip file to store what + are called "NTFS Times" and "Unix(tm) times" for a file. These are the + last write, last access, and file creation + times of a particular file. These metadata are not actually specific + to NTFS or Unix. They are tracked for each file by NTFS and by various + Unix filesystems, but they are also tracked by other filesystems, too. + The key point is that the times are formatted in the zip file + in the same way that NTFS formats the time (ticks since win32 epoch), + or in the same way that Unix formats the time (seconds since Unix + epoch). As with the DOS time, any tool or library running on any + operating system is capable of formatting a time in one of these ways + and embedding it into the zip file. + + + + These extended times are higher precision quantities than the DOS time. + As described above, the (DOS) LastModified has a precision of 2 seconds. + The Unix time is stored with a precision of 1 second. The NTFS time is + stored with a precision of 0.0000001 seconds. The quantities are easily + convertible, except for the loss of precision you may incur. + + + + A zip archive can store the {C,A,M} times in NTFS format, in Unix format, + or not at all. Often a tool running on Unix or Mac will embed the times + in Unix format (1 second precision), while WinZip running on Windows might + embed the times in NTFS format (precision of of 0.0000001 seconds). When + reading a zip file with these "extended" times, in either format, + DotNetZip represents the values with the + ModifiedTime, AccessedTime and CreationTime + properties on the ZipEntry. + + + + While any zip application or library, regardless of the platform it + runs on, could use any of the time formats allowed by the ZIP + specification, not all zip tools or libraries do support all these + formats. Storing the higher-precision times for each entry is + optional for zip files, and many tools and libraries don't use the + higher precision quantities at all. The old DOS time, represented by + , is guaranteed to be present, though it + sometimes unset. + + + + Ok, getting back to the question about how the LastModified + property relates to this ModifiedTime + property... LastModified is always set, while + ModifiedTime is not. (The other times stored in the NTFS + times extension, CreationTime and AccessedTime also + may not be set on an entry that is read from an existing zip file.) + When reading a zip file, then LastModified takes the DOS time + that is stored with the file. If the DOS time has been stored as zero + in the zipfile, then this library will use DateTime.Now for the + LastModified value. If the ZIP file was created by an evolved + tool, then there will also be higher precision NTFS or Unix times in + the zip file. In that case, this library will read those times, and + set LastModified and ModifiedTime to the same value, the + one corresponding to the last write time of the file. If there are no + higher precision times stored for the entry, then ModifiedTime + remains unset (likewise AccessedTime and CreationTime), + and LastModified keeps its DOS time. + + + + When creating zip files with this library, by default the extended time + properties (ModifiedTime, AccessedTime, and + CreationTime) are set on the ZipEntry instance, and these data are + stored in the zip archive for each entry, in NTFS format. If you add an + entry from an actual filesystem file, then the entry gets the actual file + times for that file, to NTFS-level precision. If you add an entry from a + stream, or a string, then the times get the value DateTime.Now. In + this case LastModified and ModifiedTime will be identical, + to 2 seconds of precision. You can explicitly set the + CreationTime, AccessedTime, and ModifiedTime of an + entry using the property setters. If you want to set all of those + quantities, it's more efficient to use the method. Those + changes are not made permanent in the zip file until you call or one of its cousins. + + + + When creating a zip file, you can override the default behavior of + this library for formatting times in the zip file, disabling the + embedding of file times in NTFS format or enabling the storage of file + times in Unix format, or both. You may want to do this, for example, + when creating a zip file on Windows, that will be consumed on a Mac, + by an application that is not hip to the "NTFS times" format. To do + this, use the and + properties. A valid zip + file may store the file times in both formats. But, there are no + guarantees that a program running on Mac or Linux will gracefully + handle the NTFS-formatted times when Unix times are present, or that a + non-DotNetZip-powered application running on Windows will be able to + handle file times in Unix format. DotNetZip will always do something + reasonable; other libraries or tools may not. When in doubt, test. + + + + I'll bet you didn't think one person could type so much about time, eh? + And reading it was so enjoyable, too! Well, in appreciation, maybe you + should donate? + + + + + + + + + + + Last Access time for the file represented by the entry. + + + This value may or may not be meaningful. If the ZipEntry was read from an existing + Zip archive, this information may not be available. For an explanation of why, see + . + + + + + + + + The file creation time for the file represented by the entry. + + + + This value may or may not be meaningful. If the ZipEntry was read + from an existing zip archive, and the creation time was not set on the entry + when the zip file was created, then this property may be meaningless. For an + explanation of why, see . + + + + + + + + Sets the NTFS Creation, Access, and Modified times for the given entry. + + + + + When adding an entry from a file or directory, the Creation, Access, and + Modified times for the given entry are automatically set from the + filesystem values. When adding an entry from a stream or string, the + values are implicitly set to DateTime.Now. The application may wish to + set these values to some arbitrary value, before saving the archive, and + can do so using the various setters. If you want to set all of the times, + this method is more efficient. + + + + The values you set here will be retrievable with the , and properties. + + + + When this method is called, if both and are false, then the + EmitTimesInWindowsFormatWhenSaving flag is automatically set. + + + + DateTime values provided here without a DateTimeKind are assumed to be Local Time. + + + + the creation time of the entry. + the last access time of the entry. + the last modified time of the entry. + + + + + + + + + + Specifies whether the Creation, Access, and Modified times for the given + entry will be emitted in "Windows format" when the zip archive is saved. + + + + + An application creating a zip archive can use this flag to explicitly + specify that the file times for the entry should or should not be stored + in the zip archive in the format used by Windows. The default value of + this property is true. + + + + When adding an entry from a file or directory, the Creation (), Access (), and Modified + () times for the given entry are automatically + set from the filesystem values. When adding an entry from a stream or + string, all three values are implicitly set to DateTime.Now. Applications + can also explicitly set those times by calling . + + + + PKWARE's + zip specification describes multiple ways to format these times in a + zip file. One is the format Windows applications normally use: 100ns ticks + since Jan 1, 1601 UTC. The other is a format Unix applications typically + use: seconds since January 1, 1970 UTC. Each format can be stored in an + "extra field" in the zip entry when saving the zip archive. The former + uses an extra field with a Header Id of 0x000A, while the latter uses a + header ID of 0x5455. + + + + Not all zip tools and libraries can interpret these fields. Windows + compressed folders is one that can read the Windows Format timestamps, + while I believe the Infozip + tools can read the Unix format timestamps. Although the time values are + easily convertible, subject to a loss of precision, some tools and + libraries may be able to read only one or the other. DotNetZip can read or + write times in either or both formats. + + + + The times stored are taken from , , and . + + + + This property is not mutually exclusive from the property. It is + possible that a zip entry can embed the timestamps in both forms, one + form, or neither. But, there are no guarantees that a program running on + Mac or Linux will gracefully handle NTFS Formatted times, or that a + non-DotNetZip-powered application running on Windows will be able to + handle file times in Unix format. When in doubt, test. + + + + Normally you will use the ZipFile.EmitTimesInWindowsFormatWhenSaving + property, to specify the behavior for all entries in a zip, rather than + the property on each individual entry. + + + + + + + + + + + + + Specifies whether the Creation, Access, and Modified times for the given + entry will be emitted in "Unix(tm) format" when the zip archive is saved. + + + + + An application creating a zip archive can use this flag to explicitly + specify that the file times for the entry should or should not be stored + in the zip archive in the format used by Unix. By default this flag is + false, meaning the Unix-format times are not stored in the zip + archive. + + + + When adding an entry from a file or directory, the Creation (), Access (), and Modified + () times for the given entry are automatically + set from the filesystem values. When adding an entry from a stream or + string, all three values are implicitly set to DateTime.Now. Applications + can also explicitly set those times by calling . + + + + PKWARE's + zip specification describes multiple ways to format these times in a + zip file. One is the format Windows applications normally use: 100ns ticks + since Jan 1, 1601 UTC. The other is a format Unix applications typically + use: seconds since Jan 1, 1970 UTC. Each format can be stored in an + "extra field" in the zip entry when saving the zip archive. The former + uses an extra field with a Header Id of 0x000A, while the latter uses a + header ID of 0x5455. + + + + Not all tools and libraries can interpret these fields. Windows + compressed folders is one that can read the Windows Format timestamps, + while I believe the Infozip + tools can read the Unix format timestamps. Although the time values are + easily convertible, subject to a loss of precision, some tools and + libraries may be able to read only one or the other. DotNetZip can read or + write times in either or both formats. + + + + The times stored are taken from , , and . + + + + This property is not mutually exclusive from the property. It is + possible that a zip entry can embed the timestamps in both forms, one + form, or neither. But, there are no guarantees that a program running on + Mac or Linux will gracefully handle NTFS Formatted times, or that a + non-DotNetZip-powered application running on Windows will be able to + handle file times in Unix format. When in doubt, test. + + + + Normally you will use the ZipFile.EmitTimesInUnixFormatWhenSaving + property, to specify the behavior for all entries, rather than the + property on each individual entry. + + + + + + + + + + + + + The type of timestamp attached to the ZipEntry. + + + + This property is valid only for a ZipEntry that was read from a zip archive. + It indicates the type of timestamp attached to the entry. + + + + + + + + The file attributes for the entry. + + + + + + The attributes in NTFS include + ReadOnly, Archive, Hidden, System, and Indexed. When adding a + ZipEntry to a ZipFile, these attributes are set implicitly when + adding an entry from the filesystem. When adding an entry from a stream + or string, the Attributes are not set implicitly. Regardless of the way + an entry was added to a ZipFile, you can set the attributes + explicitly if you like. + + + + When reading a ZipEntry from a ZipFile, the attributes are + set according to the data stored in the ZipFile. If you extract the + entry from the archive to a filesystem file, DotNetZip will set the + attributes on the resulting file accordingly. + + + + The attributes can be set explicitly by the application. For example the + application may wish to set the FileAttributes.ReadOnly bit for all + entries added to an archive, so that on unpack, this attribute will be set + on the extracted file. Any changes you make to this property are made + permanent only when you call a Save() method on the ZipFile + instance that contains the ZipEntry. + + + + For example, an application may wish to zip up a directory and set the + ReadOnly bit on every file in the archive, so that upon later extraction, + the resulting files will be marked as ReadOnly. Not every extraction tool + respects these attributes, but if you unpack with DotNetZip, as for + example in a self-extracting archive, then the attributes will be set as + they are stored in the ZipFile. + + + + These attributes may not be interesting or useful if the resulting archive + is extracted on a non-Windows platform. How these attributes get used + upon extraction depends on the platform and tool used. + + + + + + + The name of the filesystem file, referred to by the ZipEntry. + + + + + This property specifies the thing-to-be-zipped on disk, and is set only + when the ZipEntry is being created from a filesystem file. If the + ZipFile is instantiated by reading an existing .zip archive, then + the LocalFileName will be null (Nothing in VB). + + + + When it is set, the value of this property may be different than , which is the path used in the archive itself. If you + call Zip.AddFile("foop.txt", AlternativeDirectory), then the path + used for the ZipEntry within the zip archive will be different + than this path. + + + + If the entry is being added from a stream, then this is null (Nothing in VB). + + + + + + + + The name of the file contained in the ZipEntry. + + + + + + This is the name of the entry in the ZipFile itself. When creating + a zip archive, if the ZipEntry has been created from a filesystem + file, via a call to or , or a related overload, the value + of this property is derived from the name of that file. The + FileName property does not include drive letters, and may include a + different directory path, depending on the value of the + directoryPathInArchive parameter used when adding the entry into + the ZipFile. + + + + In some cases there is no related filesystem file - for example when a + ZipEntry is created using or one of the similar overloads. In this case, the value of + this property is derived from the fileName and the directory path passed + to that method. + + + + When reading a zip file, this property takes the value of the entry name + as stored in the zip file. If you extract such an entry, the extracted + file will take the name given by this property. + + + + Applications can set this property when creating new zip archives or when + reading existing archives. When setting this property, the actual value + that is set will replace backslashes with forward slashes, in accordance + with the Zip + specification, for compatibility with Unix(tm) and ... get + this.... Amiga! + + + + If an application reads a ZipFile via or a related overload, and then explicitly + sets the FileName on an entry contained within the ZipFile, and + then calls , the application will effectively + rename the entry within the zip archive. + + + + If an application sets the value of FileName, then calls + Extract() on the entry, the entry is extracted to a file using the + newly set value as the filename. The FileName value is made + permanent in the zip archive only after a call to one of the + ZipFile.Save() methods on the ZipFile that contains the + ZipEntry. + + + + If an application attempts to set the FileName to a value that + would result in a duplicate entry in the ZipFile, an exception is + thrown. + + + + When a ZipEntry is contained within a ZipFile, applications + cannot rename the entry within the context of a foreach (For + Each in VB) loop, because of the way the ZipFile stores + entries. If you need to enumerate through all the entries and rename one + or more of them, use ZipFile.EntriesSorted as the + collection. See also, ZipFile.GetEnumerator(). + + + + + + + The stream that provides content for the ZipEntry. + + + + + + The application can use this property to set the input stream for an + entry on a just-in-time basis. Imagine a scenario where the application + creates a ZipFile comprised of content obtained from hundreds of + files, via calls to AddFile(). The DotNetZip library opens streams + on these files on a just-in-time basis, only when writing the entry out to + an external store within the scope of a ZipFile.Save() call. Only + one input stream is opened at a time, as each entry is being written out. + + + + Now imagine a different application that creates a ZipFile + with content obtained from hundreds of streams, added through . Normally the + application would supply an open stream to that call. But when large + numbers of streams are being added, this can mean many open streams at one + time, unnecessarily. + + + + To avoid this, call and specify delegates that open and close the stream at + the time of Save. + + + + + Setting the value of this property when the entry was not added from a + stream (for example, when the ZipEntry was added with or , or when the entry was added by + reading an existing zip archive) will throw an exception. + + + + + + + + A flag indicating whether the InputStream was provided Just-in-time. + + + + + + When creating a zip archive, an application can obtain content for one or + more of the ZipEntry instances from streams, using the method. At the time + of calling that method, the application can supply null as the value of + the stream parameter. By doing so, the application indicates to the + library that it will provide a stream for the entry on a just-in-time + basis, at the time one of the ZipFile.Save() methods is called and + the data for the various entries are being compressed and written out. + + + + In this case, the application can set the + property, typically within the SaveProgress event (event type: ) for that entry. + + + + The application will later want to call Close() and Dispose() on that + stream. In the SaveProgress event, when the event type is , the application can + do so. This flag indicates that the stream has been provided by the + application on a just-in-time basis and that it is the application's + responsibility to call Close/Dispose on that stream. + + + + + + + + An enum indicating the source of the ZipEntry. + + + + + The version of the zip engine needed to read the ZipEntry. + + + + + This is a readonly property, indicating the version of the Zip + specification that the extracting tool or library must support to + extract the given entry. Generally higher versions indicate newer + features. Older zip engines obviously won't know about new features, and + won't be able to extract entries that depend on those newer features. + + + + + value + Features + + + + 20 + a basic Zip Entry, potentially using PKZIP encryption. + + + + + 45 + The ZIP64 extension is used on the entry. + + + + + 46 + File is compressed using BZIP2 compression* + + + + 50 + File is encrypted using PkWare's DES, 3DES, (broken) RC2 or RC4 + + + + 51 + File is encrypted using PKWare's AES encryption or corrected RC2 encryption. + + + + 52 + File is encrypted using corrected RC2-64 encryption** + + + + 61 + File is encrypted using non-OAEP key wrapping*** + + + + 63 + File is compressed using LZMA, PPMd+, Blowfish, or Twofish + + + + + + There are other values possible, not listed here. DotNetZip supports + regular PKZip encryption, and ZIP64 extensions. DotNetZip cannot extract + entries that require a zip engine higher than 45. + + + + This value is set upon reading an existing zip file, or after saving a zip + archive. + + + + + + The comment attached to the ZipEntry. + + + + + Each entry in a zip file can optionally have a comment associated to + it. The comment might be displayed by a zip tool during extraction, for + example. + + + + By default, the Comment is encoded in IBM437 code page. You can + specify an alternative with and + . + + + + + + + + Indicates whether the entry requires ZIP64 extensions. + + + + + + This property is null (Nothing in VB) until a Save() method on the + containing instance has been called. The property is + non-null (HasValue is true) only after a Save() method has + been called. + + + + After the containing ZipFile has been saved, the Value of this + property is true if any of the following three conditions holds: the + uncompressed size of the entry is larger than 0xFFFFFFFF; the compressed + size of the entry is larger than 0xFFFFFFFF; the relative offset of the + entry within the zip archive is larger than 0xFFFFFFFF. These quantities + are not known until a Save() is attempted on the zip archive and + the compression is applied. + + + + If none of the three conditions holds, then the Value is false. + + + + A Value of false does not indicate that the entry, as saved in the + zip archive, does not use ZIP64. It merely indicates that ZIP64 is + not required. An entry may use ZIP64 even when not required if + the property on the containing + ZipFile instance is set to , or if + the property on the containing + ZipFile instance is set to + and the output stream was not seekable. + + + + + + + + Indicates whether the entry actually used ZIP64 extensions, as it was most + recently written to the output file or stream. + + + + + + This Nullable property is null (Nothing in VB) until a Save() + method on the containing instance has been + called. HasValue is true only after a Save() method has been + called. + + + + The value of this property for a particular ZipEntry may change + over successive calls to Save() methods on the containing ZipFile, + even if the file that corresponds to the ZipEntry does not. This + may happen if other entries contained in the ZipFile expand, + causing the offset for this particular entry to exceed 0xFFFFFFFF. + + + + + + + The bitfield for the entry as defined in the zip spec. You probably + never need to look at this. + + + + + You probably do not need to concern yourself with the contents of this + property, but in case you do: + + + + + bit + meaning + + + + 0 + set if encryption is used. + + + + 1-2 + + set to determine whether normal, max, fast deflation. DotNetZip library + always leaves these bits unset when writing (indicating "normal" + deflation"), but can read an entry with any value here. + + + + + 3 + + Indicates that the Crc32, Compressed and Uncompressed sizes are zero in the + local header. This bit gets set on an entry during writing a zip file, when + it is saved to a non-seekable output stream. + + + + + + 4 + reserved for "enhanced deflating". This library doesn't do enhanced deflating. + + + + 5 + set to indicate the zip is compressed patched data. This library doesn't do that. + + + + 6 + + set if PKWare's strong encryption is used (must also set bit 1 if bit 6 is + set). This bit is not set if WinZip's AES encryption is set. + + + + 7 + not used + + + + 8 + not used + + + + 9 + not used + + + + 10 + not used + + + + 11 + + Language encoding flag (EFS). If this bit is set, the filename and comment + fields for this file must be encoded using UTF-8. This library currently + does not support UTF-8. + + + + + 12 + Reserved by PKWARE for enhanced compression. + + + + 13 + + Used when encrypting the Central Directory to indicate selected data + values in the Local Header are masked to hide their actual values. See + the section in the Zip + specification describing the Strong Encryption Specification for + details. + + + + + 14 + Reserved by PKWARE. + + + + 15 + Reserved by PKWARE. + + + + + + + + + The compression method employed for this ZipEntry. + + + + + + The + Zip specification allows a variety of compression methods. This + library supports just two: 0x08 = Deflate. 0x00 = Store (no compression), + for reading or writing. + + + + When reading an entry from an existing zipfile, the value you retrieve + here indicates the compression method used on the entry by the original + creator of the zip. When writing a zipfile, you can specify either 0x08 + (Deflate) or 0x00 (None). If you try setting something else, you will get + an exception. + + + + You may wish to set CompressionMethod to CompressionMethod.None (0) + when zipping already-compressed data like a jpg, png, or mp3 file. + This can save time and cpu cycles. + + + + When setting this property on a ZipEntry that is read from an + existing zip file, calling ZipFile.Save() will cause the new + CompressionMethod to be used on the entry in the newly saved zip file. + + + + Setting this property may have the side effect of modifying the + CompressionLevel property. If you set the CompressionMethod to a + value other than None, and CompressionLevel is previously + set to None, then CompressionLevel will be set to + Default. + + + + + + + In this example, the first entry added to the zip archive uses the default + behavior - compression is used where it makes sense. The second entry, + the MP3 file, is added to the archive without being compressed. + + using (ZipFile zip = new ZipFile(ZipFileToCreate)) + { + ZipEntry e1= zip.AddFile(@"notes\Readme.txt"); + ZipEntry e2= zip.AddFile(@"music\StopThisTrain.mp3"); + e2.CompressionMethod = CompressionMethod.None; + zip.Save(); + } + + + + Using zip As New ZipFile(ZipFileToCreate) + zip.AddFile("notes\Readme.txt") + Dim e2 as ZipEntry = zip.AddFile("music\StopThisTrain.mp3") + e2.CompressionMethod = CompressionMethod.None + zip.Save + End Using + + + + + + Sets the compression level to be used for the entry when saving the zip + archive. This applies only for CompressionMethod = DEFLATE. + + + + + When using the DEFLATE compression method, Varying the compression + level used on entries can affect the size-vs-speed tradeoff when + compression and decompressing data streams or files. + + + + If you do not set this property, the default compression level is used, + which normally gives a good balance of compression efficiency and + compression speed. In some tests, using BestCompression can + double the time it takes to compress, while delivering just a small + increase in compression efficiency. This behavior will vary with the + type of data you compress. If you are in doubt, just leave this setting + alone, and accept the default. + + + + When setting this property on a ZipEntry that is read from an + existing zip file, calling ZipFile.Save() will cause the new + CompressionLevel to be used on the entry in the newly saved zip file. + + + + Setting this property may have the side effect of modifying the + CompressionMethod property. If you set the CompressionLevel + to a value other than None, CompressionMethod will be set + to Deflate, if it was previously None. + + + + Setting this property has no effect if the CompressionMethod is something + other than Deflate or None. + + + + + + + + The compressed size of the file, in bytes, within the zip archive. + + + + When reading a ZipFile, this value is read in from the existing + zip file. When creating or updating a ZipFile, the compressed + size is computed during compression. Therefore the value on a + ZipEntry is valid after a call to Save() (or one of its + overloads) in that case. + + + + + + + The size of the file, in bytes, before compression, or after extraction. + + + + When reading a ZipFile, this value is read in from the existing + zip file. When creating or updating a ZipFile, the uncompressed + size is computed during compression. Therefore the value on a + ZipEntry is valid after a call to Save() (or one of its + overloads) in that case. + + + + + + + The ratio of compressed size to uncompressed size of the ZipEntry. + + + + + This is a ratio of the compressed size to the uncompressed size of the + entry, expressed as a double in the range of 0 to 100+. A value of 100 + indicates no compression at all. It could be higher than 100 when the + compression algorithm actually inflates the data, as may occur for small + files, or uncompressible data that is encrypted. + + + + You could format it for presentation to a user via a format string of + "{3,5:F0}%" to see it as a percentage. + + + + If the size of the original uncompressed file is 0, implying a + denominator of 0, the return value will be zero. + + + + This property is valid after reading in an existing zip file, or after + saving the ZipFile that contains the ZipEntry. You cannot know the + effect of a compression transform until you try it. + + + + + + + The 32-bit CRC (Cyclic Redundancy Check) on the contents of the ZipEntry. + + + + + You probably don't need to concern yourself with this. It is used + internally by DotNetZip to verify files or streams upon extraction. + + The value is a 32-bit + CRC using 0xEDB88320 for the polynomial. This is the same CRC-32 used in + PNG, MPEG-2, and other protocols and formats. It is a read-only property; when + creating a Zip archive, the CRC for each entry is set only after a call to + Save() on the containing ZipFile. When reading an existing zip file, the value + of this property reflects the stored CRC for the entry. + + + + + + True if the entry is a directory (not a file). + This is a readonly property on the entry. + + + + + A derived property that is true if the entry uses encryption. + + + + + This is a readonly property on the entry. When reading a zip file, + the value for the ZipEntry is determined by the data read + from the zip file. After saving a ZipFile, the value of this + property for each ZipEntry indicates whether encryption was + actually used (which will have been true if the was set and the property + was something other than . + + + + + + Set this to specify which encryption algorithm to use for the entry when + saving it to a zip archive. + + + + + + Set this property in order to encrypt the entry when the ZipFile is + saved. When setting this property, you must also set a on the entry. If you set a value other than on this property and do not set a + Password then the entry will not be encrypted. The ZipEntry + data is encrypted as the ZipFile is saved, when you call or one of its cousins on the containing + ZipFile instance. You do not need to specify the Encryption + when extracting entries from an archive. + + + + The Zip specification from PKWare defines a set of encryption algorithms, + and the data formats for the zip archive that support them, and PKWare + supports those algorithms in the tools it produces. Other vendors of tools + and libraries, such as WinZip or Xceed, typically support a + subset of the algorithms specified by PKWare. These tools can + sometimes support additional different encryption algorithms and data + formats, not specified by PKWare. The AES Encryption specified and + supported by WinZip is the most popular example. This library supports a + subset of the complete set of algorithms specified by PKWare and other + vendors. + + + + There is no common, ubiquitous multi-vendor standard for strong encryption + within zip files. There is broad support for so-called "traditional" Zip + encryption, sometimes called Zip 2.0 encryption, as specified + by PKWare, but this encryption is considered weak and + breakable. This library currently supports the Zip 2.0 "weak" encryption, + and also a stronger WinZip-compatible AES encryption, using either 128-bit + or 256-bit key strength. If you want DotNetZip to support an algorithm + that is not currently supported, call the author of this library and maybe + we can talk business. + + + + The class also has a property. In most cases you will use + that property when setting encryption. This property takes + precedence over any Encryption set on the ZipFile itself. + Typically, you would use the per-entry Encryption when most entries in the + zip archive use one encryption algorithm, and a few entries use a + different one. If all entries in the zip file use the same Encryption, + then it is simpler to just set this property on the ZipFile itself, when + creating a zip archive. + + + + Some comments on updating archives: If you read a ZipFile, you can + modify the Encryption on an encrypted entry: you can remove encryption + from an entry that was encrypted; you can encrypt an entry that was not + encrypted previously; or, you can change the encryption algorithm. The + changes in encryption are not made permanent until you call Save() on the + ZipFile. To effect changes in encryption, the entry content is + streamed through several transformations, depending on the modification + the application has requested. For example if the entry is not encrypted + and the application sets Encryption to PkzipWeak, then at + the time of Save(), the original entry is read and decompressed, + then re-compressed and encrypted. Conversely, if the original entry is + encrypted with PkzipWeak encryption, and the application sets the + Encryption property to WinZipAes128, then at the time of + Save(), the original entry is decrypted via PKZIP encryption and + decompressed, then re-compressed and re-encrypted with AES. This all + happens automatically within the library, but it can be time-consuming for + large entries. + + + + Additionally, when updating archives, it is not possible to change the + password when changing the encryption algorithm. To change both the + algorithm and the password, you need to Save() the zipfile twice. First + set the Encryption to None, then call Save(). Then set the + Encryption to the new value (not "None"), then call Save() + once again. + + + + The WinZip AES encryption algorithms are not supported on the .NET Compact + Framework. + + + + + + This example creates a zip archive that uses encryption, and then extracts + entries from the archive. When creating the zip archive, the ReadMe.txt + file is zipped without using a password or encryption. The other file + uses encryption. + + + // Create a zip archive with AES Encryption. + using (ZipFile zip = new ZipFile()) + { + zip.AddFile("ReadMe.txt") + ZipEntry e1= zip.AddFile("2008-Regional-Sales-Report.pdf"); + e1.Encryption= EncryptionAlgorithm.WinZipAes256; + e1.Password= "Top.Secret.No.Peeking!"; + zip.Save("EncryptedArchive.zip"); + } + + // Extract a zip archive that uses AES Encryption. + // You do not need to specify the algorithm during extraction. + using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip")) + { + // Specify the password that is used during extraction, for + // all entries that require a password: + zip.Password= "Top.Secret.No.Peeking!"; + zip.ExtractAll("extractDirectory"); + } + + + + ' Create a zip that uses Encryption. + Using zip As New ZipFile() + zip.AddFile("ReadMe.txt") + Dim e1 as ZipEntry + e1= zip.AddFile("2008-Regional-Sales-Report.pdf") + e1.Encryption= EncryptionAlgorithm.WinZipAes256 + e1.Password= "Top.Secret.No.Peeking!" + zip.Save("EncryptedArchive.zip") + End Using + + ' Extract a zip archive that uses AES Encryption. + ' You do not need to specify the algorithm during extraction. + Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip")) + ' Specify the password that is used during extraction, for + ' all entries that require a password: + zip.Password= "Top.Secret.No.Peeking!" + zip.ExtractAll("extractDirectory") + End Using + + + + + + Thrown in the setter if EncryptionAlgorithm.Unsupported is specified. + + + ZipEntry.Password + ZipFile.Encryption + + + + The Password to be used when encrypting a ZipEntry upon + ZipFile.Save(), or when decrypting an entry upon Extract(). + + + + + This is a write-only property on the entry. Set this to request that the + entry be encrypted when writing the zip archive, or set it to specify the + password to be used when extracting an existing entry that is encrypted. + + + + The password set here is implicitly used to encrypt the entry during the + operation, or to decrypt during the or operation. If you set + the Password on a ZipEntry after calling Save(), there is no + effect. + + + + Consider setting the property when using a + password. Answering concerns that the standard password protection + supported by all zip tools is weak, WinZip has extended the ZIP + specification with a way to use AES Encryption to protect entries in the + Zip file. Unlike the "PKZIP 2.0" encryption specified in the PKZIP + specification, AES + Encryption uses a standard, strong, tested, encryption + algorithm. DotNetZip can create zip archives that use WinZip-compatible + AES encryption, if you set the property. But, + archives created that use AES encryption may not be readable by all other + tools and libraries. For example, Windows Explorer cannot read a + "compressed folder" (a zip file) that uses AES encryption, though it can + read a zip file that uses "PKZIP encryption." + + + + The class also has a + property. This property takes precedence over any password set on the + ZipFile itself. Typically, you would use the per-entry Password when most + entries in the zip archive use one password, and a few entries use a + different password. If all entries in the zip file use the same password, + then it is simpler to just set this property on the ZipFile itself, + whether creating a zip archive or extracting a zip archive. + + + + Some comments on updating archives: If you read a ZipFile, you + cannot modify the password on any encrypted entry, except by extracting + the entry with the original password (if any), removing the original entry + via , and then adding a new + entry with a new Password. + + + + For example, suppose you read a ZipFile, and there is an encrypted + entry. Setting the Password property on that ZipEntry and then + calling Save() on the ZipFile does not update the password + on that entry in the archive. Neither is an exception thrown. Instead, + what happens during the Save() is the existing entry is copied + through to the new zip archive, in its original encrypted form. Upon + re-reading that archive, the entry can be decrypted with its original + password. + + + + If you read a ZipFile, and there is an un-encrypted entry, you can set the + Password on the entry and then call Save() on the ZipFile, and get + encryption on that entry. + + + + + + + This example creates a zip file with two entries, and then extracts the + entries from the zip file. When creating the zip file, the two files are + added to the zip file using password protection. Each entry uses a + different password. During extraction, each file is extracted with the + appropriate password. + + + // create a file with encryption + using (ZipFile zip = new ZipFile()) + { + ZipEntry entry; + entry= zip.AddFile("Declaration.txt"); + entry.Password= "123456!"; + entry = zip.AddFile("Report.xls"); + entry.Password= "1Secret!"; + zip.Save("EncryptedArchive.zip"); + } + + // extract entries that use encryption + using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip")) + { + ZipEntry entry; + entry = zip["Declaration.txt"]; + entry.Password = "123456!"; + entry.Extract("extractDir"); + entry = zip["Report.xls"]; + entry.Password = "1Secret!"; + entry.Extract("extractDir"); + } + + + + + Using zip As New ZipFile + Dim entry as ZipEntry + entry= zip.AddFile("Declaration.txt") + entry.Password= "123456!" + entry = zip.AddFile("Report.xls") + entry.Password= "1Secret!" + zip.Save("EncryptedArchive.zip") + End Using + + + ' extract entries that use encryption + Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip")) + Dim entry as ZipEntry + entry = zip("Declaration.txt") + entry.Password = "123456!" + entry.Extract("extractDir") + entry = zip("Report.xls") + entry.Password = "1Secret!" + entry.Extract("extractDir") + End Using + + + + + + + ZipFile.Password + + + + The action the library should take when extracting a file that already exists. + + + + + This property affects the behavior of the Extract methods (one of the + Extract() or ExtractWithPassword() overloads), when + extraction would would overwrite an existing filesystem file. If you do + not set this property, the library throws an exception when extracting + an entry would overwrite an existing file. + + + + This property has no effect when extracting to a stream, or when the file to be + extracted does not already exist. + + + + + + + This example shows how to set the ExtractExistingFile property in + an ExtractProgress event, in response to user input. The + ExtractProgress event is invoked if and only if the + ExtractExistingFile property was previously set to + ExtractExistingFileAction.InvokeExtractProgressEvent. + + public static void ExtractProgress(object sender, ExtractProgressEventArgs e) + { + if (e.EventType == ZipProgressEventType.Extracting_BeforeExtractEntry) + Console.WriteLine("extract {0} ", e.CurrentEntry.FileName); + + else if (e.EventType == ZipProgressEventType.Extracting_ExtractEntryWouldOverwrite) + { + ZipEntry entry = e.CurrentEntry; + string response = null; + // Ask the user if he wants overwrite the file + do + { + Console.Write("Overwrite {0} in {1} ? (y/n/C) ", entry.FileName, e.ExtractLocation); + response = Console.ReadLine(); + Console.WriteLine(); + + } while (response != null && response[0]!='Y' && + response[0]!='N' && response[0]!='C'); + + if (response[0]=='C') + e.Cancel = true; + else if (response[0]=='Y') + entry.ExtractExistingFile = ExtractExistingFileAction.OverwriteSilently; + else + entry.ExtractExistingFile= ExtractExistingFileAction.DoNotOverwrite; + } + } + + + + + + The action to take when an error is encountered while + opening or reading files as they are saved into a zip archive. + + + + + Errors can occur within a call to ZipFile.Save, as the various files contained + in a ZipFile are being saved into the zip archive. During the + Save, DotNetZip will perform a File.Open on the file + associated to the ZipEntry, and then will read the entire contents of + the file as it is zipped. Either the open or the Read may fail, because + of lock conflicts or other reasons. Using this property, you can + specify the action to take when such errors occur. + + + + Typically you will NOT set this property on individual ZipEntry + instances. Instead, you will set the ZipFile.ZipErrorAction property on + the ZipFile instance, before adding any entries to the + ZipFile. If you do this, errors encountered on behalf of any of + the entries in the ZipFile will be handled the same way. + + + + But, if you use a handler, you will want + to set this property on the ZipEntry within the handler, to + communicate back to DotNetZip what you would like to do with the + particular error. + + + + + + + + + Indicates whether the entry was included in the most recent save. + + + An entry can be excluded or skipped from a save if there is an error + opening or reading the entry. + + + + + + A callback that allows the application to specify the compression to use + for a given entry that is about to be added to the zip archive. + + + + + See + + + + + + Set to indicate whether to use UTF-8 encoding for filenames and comments. + + + + + + If this flag is set, the comment and filename for the entry will be + encoded with UTF-8, as described in the Zip + specification, if necessary. "Necessary" means, the filename or + entry comment (if any) cannot be reflexively encoded and decoded using the + default code page, IBM437. + + + + Setting this flag to true is equivalent to setting to System.Text.Encoding.UTF8. + + + + This flag has no effect or relation to the text encoding used within the + file itself. + + + + + + + The text encoding to use for the FileName and Comment on this ZipEntry, + when the default encoding is insufficient. + + + + + + Don't use this property. See . + + + + + + + Specifies the alternate text encoding used by this ZipEntry + + + + The default text encoding used in Zip files for encoding filenames and + comments is IBM437, which is something like a superset of ASCII. In + cases where this is insufficient, applications can specify an + alternate encoding. + + + When creating a zip file, the usage of the alternate encoding is + governed by the property. + Typically you would set both properties to tell DotNetZip to employ an + encoding that is not IBM437 in the zipfile you are creating. + + + Keep in mind that because the ZIP specification states that the only + valid encodings to use are IBM437 and UTF-8, if you use something + other than that, then zip tools and libraries may not be able to + successfully read the zip archive you generate. + + + The zip specification states that applications should presume that + IBM437 is in use, except when a special bit is set, which indicates + UTF-8. There is no way to specify an arbitrary code page, within the + zip file itself. When you create a zip file encoded with gb2312 or + ibm861 or anything other than IBM437 or UTF-8, then the application + that reads the zip file needs to "know" which code page to use. In + some cases, the code page used when reading is chosen implicitly. For + example, WinRar uses the ambient code page for the host desktop + operating system. The pitfall here is that if you create a zip in + Copenhagen and send it to Tokyo, the reader of the zipfile may not be + able to decode successfully. + + + + This example shows how to create a zipfile encoded with a + language-specific encoding: + + using (var zip = new ZipFile()) + { + zip.AlternateEnoding = System.Text.Encoding.GetEncoding("ibm861"); + zip.AlternateEnodingUsage = ZipOption.Always; + zip.AddFileS(arrayOfFiles); + zip.Save("Myarchive-Encoded-in-IBM861.zip"); + } + + + + + + + Describes if and when this instance should apply + AlternateEncoding to encode the FileName and Comment, when + saving. + + + + + + Indicates whether an entry is marked as a text file. Be careful when + using on this property. Unless you have a good reason, you should + probably ignore this property. + + + + + The ZIP format includes a provision for specifying whether an entry in + the zip archive is a text or binary file. This property exposes that + metadata item. Be careful when using this property: It's not clear + that this property as a firm meaning, across tools and libraries. + + + + To be clear, when reading a zip file, the property value may or may + not be set, and its value may or may not be valid. Not all entries + that you may think of as "text" entries will be so marked, and entries + marked as "text" are not guaranteed in any way to be text entries. + Whether the value is set and set correctly depends entirely on the + application that produced the zip file. + + + + There are many zip tools available, and when creating zip files, some + of them "respect" the IsText metadata field, and some of them do not. + Unfortunately, even when an application tries to do "the right thing", + it's not always clear what "the right thing" is. + + + + There's no firm definition of just what it means to be "a text file", + and the zip specification does not help in this regard. Twenty years + ago, text was ASCII, each byte was less than 127. IsText meant, all + bytes in the file were less than 127. These days, it is not the case + that all text files have all bytes less than 127. Any unicode file + may have bytes that are above 0x7f. The zip specification has nothing + to say on this topic. Therefore, it's not clear what IsText really + means. + + + + This property merely tells a reading application what is stored in the + metadata for an entry, without guaranteeing its validity or its + meaning. + + + + When DotNetZip is used to create a zipfile, it attempts to set this + field "correctly." For example, if a file ends in ".txt", this field + will be set. Your application may override that default setting. When + writing a zip file, you must set the property before calling + Save() on the ZipFile. + + + + When reading a zip file, a more general way to decide just what kind + of file is contained in a particular entry is to use the file type + database stored in the operating system. The operating system stores + a table that says, a file with .jpg extension is a JPG image file, a + file with a .xml extension is an XML document, a file with a .txt is a + pure ASCII text document, and so on. To get this information on + Windows, you + need to read and parse the registry. + + + + + using (var zip = new ZipFile()) + { + var e = zip.UpdateFile("Descriptions.mme", ""); + e.IsText = true; + zip.Save(zipPath); + } + + + + Using zip As New ZipFile + Dim e2 as ZipEntry = zip.AddFile("Descriptions.mme", "") + e.IsText= True + zip.Save(zipPath) + End Using + + + + + Provides a string representation of the instance. + a string representation of the instance. + + + + Extract the entry to the filesystem, starting at the current + working directory. + + + + This method has a bunch of overloads! One of them is sure to + be the right one for you... If you don't like these, check + out the ExtractWithPassword() methods. + + + + + + + + + This method extracts an entry from a zip file into the current + working directory. The path of the entry as extracted is the full + path as specified in the zip archive, relative to the current + working directory. After the file is extracted successfully, the + file attributes and timestamps are set. + + + + The action taken when extraction an entry would overwrite an + existing file is determined by the property. + + + + Within the call to Extract(), the content for the entry is + written into a filesystem file, and then the last modified time of the + file is set according to the property on + the entry. See the remarks the property for + some details about the last modified time. + + + + + + + Extract the entry to a file in the filesystem, using the specified + behavior when extraction would overwrite an existing file. + + + + + See the remarks on the property, for some + details about how the last modified time of the file is set after + extraction. + + + + + The action to take if extraction would overwrite an existing file. + + + + + Extracts the entry to the specified stream. + + + + + The caller can specify any write-able stream, for example a , a , or ASP.NET's + Response.OutputStream. The content will be decrypted and + decompressed as necessary. If the entry is encrypted and no password + is provided, this method will throw. + + + The position on the stream is not reset by this method before it extracts. + You may want to call stream.Seek() before calling ZipEntry.Extract(). + + + + + the stream to which the entry should be extracted. + + + + + + Extract the entry to the filesystem, starting at the specified base + directory. + + + the pathname of the base directory + + + + + + This example extracts only the entries in a zip file that are .txt files, + into a directory called "textfiles". + + using (ZipFile zip = ZipFile.Read("PackedDocuments.zip")) + { + foreach (string s1 in zip.EntryFilenames) + { + if (s1.EndsWith(".txt")) + { + zip[s1].Extract("textfiles"); + } + } + } + + + Using zip As ZipFile = ZipFile.Read("PackedDocuments.zip") + Dim s1 As String + For Each s1 In zip.EntryFilenames + If s1.EndsWith(".txt") Then + zip(s1).Extract("textfiles") + End If + Next + End Using + + + + + + + Using this method, existing entries in the filesystem will not be + overwritten. If you would like to force the overwrite of existing + files, see the property, or call + . + + + + See the remarks on the property, for some + details about how the last modified time of the created file is set. + + + + + + Extract the entry to the filesystem, starting at the specified base + directory, and using the specified behavior when extraction would + overwrite an existing file. + + + + + See the remarks on the property, for some + details about how the last modified time of the created file is set. + + + + + + String sZipPath = "Airborne.zip"; + String sFilePath = "Readme.txt"; + String sRootFolder = "Digado"; + using (ZipFile zip = ZipFile.Read(sZipPath)) + { + if (zip.EntryFileNames.Contains(sFilePath)) + { + // use the string indexer on the zip file + zip[sFileName].Extract(sRootFolder, + ExtractExistingFileAction.OverwriteSilently); + } + } + + + + Dim sZipPath as String = "Airborne.zip" + Dim sFilePath As String = "Readme.txt" + Dim sRootFolder As String = "Digado" + Using zip As ZipFile = ZipFile.Read(sZipPath) + If zip.EntryFileNames.Contains(sFilePath) + ' use the string indexer on the zip file + zip(sFilePath).Extract(sRootFolder, _ + ExtractExistingFileAction.OverwriteSilently) + End If + End Using + + + + the pathname of the base directory + + The action to take if extraction would overwrite an existing file. + + + + + Extract the entry to the filesystem, using the current working directory + and the specified password. + + + + This method has a bunch of overloads! One of them is sure to be + the right one for you... + + + + + + + + + Existing entries in the filesystem will not be overwritten. If you + would like to force the overwrite of existing files, see the property, or call + . + + + + See the remarks on the property for some + details about how the "last modified" time of the created file is + set. + + + + + In this example, entries that use encryption are extracted using a + particular password. + + using (var zip = ZipFile.Read(FilePath)) + { + foreach (ZipEntry e in zip) + { + if (e.UsesEncryption) + e.ExtractWithPassword("Secret!"); + else + e.Extract(); + } + } + + + Using zip As ZipFile = ZipFile.Read(FilePath) + Dim e As ZipEntry + For Each e In zip + If (e.UsesEncryption) + e.ExtractWithPassword("Secret!") + Else + e.Extract + End If + Next + End Using + + + The Password to use for decrypting the entry. + + + + Extract the entry to the filesystem, starting at the specified base + directory, and using the specified password. + + + + + + + + Existing entries in the filesystem will not be overwritten. If you + would like to force the overwrite of existing files, see the property, or call + . + + + + See the remarks on the property, for some + details about how the last modified time of the created file is set. + + + + The pathname of the base directory. + The Password to use for decrypting the entry. + + + + Extract the entry to a file in the filesystem, relative to the + current directory, using the specified behavior when extraction + would overwrite an existing file. + + + + + See the remarks on the property, for some + details about how the last modified time of the created file is set. + + + + The Password to use for decrypting the entry. + + + The action to take if extraction would overwrite an existing file. + + + + + Extract the entry to the filesystem, starting at the specified base + directory, and using the specified behavior when extraction would + overwrite an existing file. + + + + See the remarks on the property, for some + details about how the last modified time of the created file is set. + + + the pathname of the base directory + + The action to take if extraction would + overwrite an existing file. + + The Password to use for decrypting the entry. + + + + Extracts the entry to the specified stream, using the specified + Password. For example, the caller could extract to Console.Out, or + to a MemoryStream. + + + + + The caller can specify any write-able stream, for example a , a , or ASP.NET's + Response.OutputStream. The content will be decrypted and + decompressed as necessary. If the entry is encrypted and no password + is provided, this method will throw. + + + The position on the stream is not reset by this method before it extracts. + You may want to call stream.Seek() before calling ZipEntry.Extract(). + + + + + + the stream to which the entry should be extracted. + + + The password to use for decrypting the entry. + + + + + Opens a readable stream corresponding to the zip entry in the + archive. The stream decompresses and decrypts as necessary, as it + is read. + + + + + + DotNetZip offers a variety of ways to extract entries from a zip + file. This method allows an application to extract an entry by + reading a . + + + + The return value is of type . Use it as you would any + stream for reading. When an application calls on that stream, it will + receive data from the zip entry that is decrypted and decompressed + as necessary. + + + + CrcCalculatorStream adds one additional feature: it keeps a + CRC32 checksum on the bytes of the stream as it is read. The CRC + value is available in the property on the + CrcCalculatorStream. When the read is complete, your + application + should check this CRC against the + property on the ZipEntry to validate the content of the + ZipEntry. You don't have to validate the entry using the CRC, but + you should, to verify integrity. Check the example for how to do + this. + + + + If the entry is protected with a password, then you need to provide + a password prior to calling , either by + setting the property on the entry, or the + property on the ZipFile + itself. Or, you can use , the + overload of OpenReader that accepts a password parameter. + + + + If you want to extract entry data into a write-able stream that is + already opened, like a , do not + use this method. Instead, use . + + + + Your application may use only one stream created by OpenReader() at + a time, and you should not call other Extract methods before + completing your reads on a stream obtained from OpenReader(). This + is because there is really only one source stream for the compressed + content. A call to OpenReader() seeks in the source stream, to the + beginning of the compressed content. A subsequent call to + OpenReader() on a different entry will seek to a different position + in the source stream, as will a call to Extract() or one of its + overloads. This will corrupt the state for the decompressing stream + from the original call to OpenReader(). + + + + The OpenReader() method works only when the ZipEntry is + obtained from an instance of ZipFile. This method will throw + an exception if the ZipEntry is obtained from a . + + + + + This example shows how to open a zip archive, then read in a named + entry via a stream. After the read loop is complete, the code + compares the calculated during the read loop with the expected CRC + on the ZipEntry, to verify the extraction. + + using (ZipFile zip = new ZipFile(ZipFileToRead)) + { + ZipEntry e1= zip["Elevation.mp3"]; + using (Ionic.Zlib.CrcCalculatorStream s = e1.OpenReader()) + { + byte[] buffer = new byte[4096]; + int n, totalBytesRead= 0; + do { + n = s.Read(buffer,0, buffer.Length); + totalBytesRead+=n; + } while (n>0); + if (s.Crc32 != e1.Crc32) + throw new Exception(string.Format("The Zip Entry failed the CRC Check. (0x{0:X8}!=0x{1:X8})", s.Crc32, e1.Crc32)); + if (totalBytesRead != e1.UncompressedSize) + throw new Exception(string.Format("We read an unexpected number of bytes. ({0}!={1})", totalBytesRead, e1.UncompressedSize)); + } + } + + + Using zip As New ZipFile(ZipFileToRead) + Dim e1 As ZipEntry = zip.Item("Elevation.mp3") + Using s As Ionic.Zlib.CrcCalculatorStream = e1.OpenReader + Dim n As Integer + Dim buffer As Byte() = New Byte(4096) {} + Dim totalBytesRead As Integer = 0 + Do + n = s.Read(buffer, 0, buffer.Length) + totalBytesRead = (totalBytesRead + n) + Loop While (n > 0) + If (s.Crc32 <> e1.Crc32) Then + Throw New Exception(String.Format("The Zip Entry failed the CRC Check. (0x{0:X8}!=0x{1:X8})", s.Crc32, e1.Crc32)) + End If + If (totalBytesRead <> e1.UncompressedSize) Then + Throw New Exception(String.Format("We read an unexpected number of bytes. ({0}!={1})", totalBytesRead, e1.UncompressedSize)) + End If + End Using + End Using + + + + The Stream for reading. + + + + Opens a readable stream for an encrypted zip entry in the archive. + The stream decompresses and decrypts as necessary, as it is read. + + + + + See the documentation on the method for + full details. This overload allows the application to specify a + password for the ZipEntry to be read. + + + + The password to use for decrypting the entry. + The Stream for reading. + + + + Pass in either basedir or s, but not both. + In other words, you can extract to a stream or to a directory (filesystem), but not both! + The Password param is required for encrypted entries. + + + + + Extract to a stream + In other words, you can extract to a stream or to a directory (filesystem), but not both! + The Password param is required for encrypted entries. + + + + + Validates that the args are consistent; returning whether the caller can return + because it's done, or not (caller should continue) + + + + + Validates that the args are consistent; returning whether the caller can return + because it's done, or not (caller should continue) + + + + + Reads one ZipEntry from the given stream. The content for + the entry does not get decompressed or decrypted. This method + basically reads metadata, and seeks. + + the ZipContainer this entry belongs to. + + true of this is the first entry being read from the stream. + + the ZipEntry read from the stream. + + + + Finds a particular segment in the given extra field. + This is used when modifying a previously-generated + extra field, in particular when removing the AES crypto + segment in the extra field. + + + + + At current cursor position in the stream, read the extra + field, and set the properties on the ZipEntry instance + appropriately. This can be called when processing the + Extra field in the Central Directory, or in the local + header. + + + + + generate and return a byte array that encodes the filename + for the entry. + + + + side effects: generate and store into _CommentBytes the + byte array for any comment attached to the entry. Also + sets _actualEncoding to indicate the actual encoding + used. The same encoding is used for both filename and + comment. + + + + + + Stores the position of the entry source stream, or, if the position is + already stored, seeks to that position. + + + + + This method is called in prep for reading the source stream. If PKZIP + encryption is used, then we need to calc the CRC32 before doing the + encryption, because the CRC is used in the 12th byte of the PKZIP + encryption header. So, we need to be able to seek backward in the source + when saving the ZipEntry. This method is called from the place that + calculates the CRC, and also from the method that does the encryption of + the file data. + + + + The first time through, this method sets the _sourceStreamOriginalPosition + field. Subsequent calls to this method seek to that position. + + + + + + Copy metadata that may have been changed by the app. We do this when + resetting the zipFile instance. If the app calls Save() on a ZipFile, then + tries to party on that file some more, we may need to Reset() it , which + means re-reading the entries and then copying the metadata. I think. + + + + + Set the input stream and get its length, if possible. The length is + used for progress updates, AND, to allow an optimization in case of + a stream/file of zero length. In that case we skip the Encrypt and + compression Stream. (like DeflateStream or BZip2OutputStream) + + + + + Prepare the given stream for output - wrap it in a CountingStream, and + then in a CRC stream, and an encryptor and deflator as appropriate. + + + + Previously this was used in ZipEntry.Write(), but in an effort to + introduce some efficiencies in that method I've refactored to put the + code inline. This method still gets called by ZipOutputStream. + + + + + + An enum that specifies the type of timestamp available on the ZipEntry. + + + + + + The last modified time of a file can be stored in multiple ways in + a zip file, and they are not mutually exclusive: + + + + + In the so-called "DOS" format, which has a 2-second precision. Values + are rounded to the nearest even second. For example, if the time on the + file is 12:34:43, then it will be stored as 12:34:44. This first value + is accessible via the LastModified property. This value is always + present in the metadata for each zip entry. In some cases the value is + invalid, or zero. + + + + In the so-called "Windows" or "NTFS" format, as an 8-byte integer + quantity expressed as the number of 1/10 milliseconds (in other words + the number of 100 nanosecond units) since January 1, 1601 (UTC). This + format is how Windows represents file times. This time is accessible + via the ModifiedTime property. + + + + In the "Unix" format, a 4-byte quantity specifying the number of seconds since + January 1, 1970 UTC. + + + + In an older format, now deprecated but still used by some current + tools. This format is also a 4-byte quantity specifying the number of + seconds since January 1, 1970 UTC. + + + + + + This bit field describes which of the formats were found in a ZipEntry that was read. + + + + + + + Default value. + + + + + A DOS timestamp with 2-second precision. + + + + + A Windows timestamp with 100-ns precision. + + + + + A Unix timestamp with 1-second precision. + + + + + A Unix timestamp with 1-second precision, stored in InfoZip v1 format. This + format is outdated and is supported for reading archives only. + + + + + The method of compression to use for a particular ZipEntry. + + + + PKWare's + ZIP Specification describes a number of distinct + cmopression methods that can be used within a zip + file. DotNetZip supports a subset of them. + + + + + No compression at all. For COM environments, the value is 0 (zero). + + + + + DEFLATE compression, as described in IETF RFC + 1951. This is the "normal" compression used in zip + files. For COM environments, the value is 8. + + + + + BZip2 compression, a compression algorithm developed by Julian Seward. + For COM environments, the value is 12. + + + + + An enum that specifies the source of the ZipEntry. + + + + + Default value. Invalid on a bonafide ZipEntry. + + + + + The entry was instantiated by calling AddFile() or another method that + added an entry from the filesystem. + + + + + The entry was instantiated via or + . + + + + + The ZipEntry was instantiated by reading a zipfile. + + + + + The content for the ZipEntry will be or was provided by the WriteDelegate. + + + + + The content for the ZipEntry will be obtained from the stream dispensed by the OpenDelegate. + The entry was instantiated via . + + + + + The content for the ZipEntry will be or was obtained from a ZipOutputStream. + + + + + An enum providing the options when an error occurs during opening or reading + of a file or directory that is being saved to a zip file. + + + + + This enum describes the actions that the library can take when an error occurs + opening or reading a file, as it is being saved into a Zip archive. + + + + In some cases an error will occur when DotNetZip tries to open a file to be + added to the zip archive. In other cases, an error might occur after the + file has been successfully opened, while DotNetZip is reading the file. + + + + The first problem might occur when calling AddDirectory() on a directory + that contains a Clipper .dbf file; the file is locked by Clipper and + cannot be opened by another process. An example of the second problem is + the ERROR_LOCK_VIOLATION that results when a file is opened by another + process, but not locked, and a range lock has been taken on the file. + Microsoft Outlook takes range locks on .PST files. + + + + + + Throw an exception when an error occurs while zipping. This is the default + behavior. (For COM clients, this is a 0 (zero).) + + + + + When an error occurs during zipping, for example a file cannot be opened, + skip the file causing the error, and continue zipping. (For COM clients, + this is a 1.) + + + + + When an error occurs during zipping, for example a file cannot be opened, + retry the operation that caused the error. Be careful with this option. If + the error is not temporary, the library will retry forever. (For COM + clients, this is a 2.) + + + + + When an error occurs, invoke the zipError event. The event type used is + . A typical use of this option: + a GUI application may wish to pop up a dialog to allow the user to view the + error that occurred, and choose an appropriate action. After your + processing in the error event, if you want to skip the file, set on the + ZipProgressEventArgs.CurrentEntry to Skip. If you want the + exception to be thrown, set ZipErrorAction on the CurrentEntry + to Throw. If you want to cancel the zip, set + ZipProgressEventArgs.Cancel to true. Cancelling differs from using + Skip in that a cancel will not save any further entries, if there are any. + (For COM clients, the value of this enum is a 3.) + + + + + The ZipFile type represents a zip archive file. + + + + + This is the main type in the DotNetZip class library. This class reads and + writes zip files, as defined in the specification + for zip files described by PKWare. The compression for this + implementation is provided by a managed-code version of Zlib, included with + DotNetZip in the classes in the Ionic.Zlib namespace. + + + + This class provides a general purpose zip file capability. Use it to read, + create, or update zip files. When you want to create zip files using a + Stream type to write the zip file, you may want to consider the class. + + + + Both the ZipOutputStream class and the ZipFile class can + be used to create zip files. Both of them support many of the common zip + features, including Unicode, different compression methods and levels, + and ZIP64. They provide very similar performance when creating zip + files. + + + + The ZipFile class is generally easier to use than + ZipOutputStream and should be considered a higher-level interface. For + example, when creating a zip file via calls to the PutNextEntry() and + Write() methods on the ZipOutputStream class, the caller is + responsible for opening the file, reading the bytes from the file, writing + those bytes into the ZipOutputStream, setting the attributes on the + ZipEntry, and setting the created, last modified, and last accessed + timestamps on the zip entry. All of these things are done automatically by a + call to ZipFile.AddFile(). + For this reason, the ZipOutputStream is generally recommended for use + only when your application emits arbitrary data, not necessarily data from a + filesystem file, directly into a zip file, and does so using a Stream + metaphor. + + + + Aside from the differences in programming model, there are other + differences in capability between the two classes. + + + + + ZipFile can be used to read and extract zip files, in addition to + creating zip files. ZipOutputStream cannot read zip files. If you want + to use a stream to read zip files, check out the class. + + + + ZipOutputStream does not support the creation of segmented or spanned + zip files. + + + + ZipOutputStream cannot produce a self-extracting archive. + + + + + Be aware that the ZipFile class implements the interface. In order for ZipFile to + produce a valid zip file, you use use it within a using clause (Using + in VB), or call the Dispose() method explicitly. See the examples + for how to employ a using clause. + + + + + + + Adds an item, either a file or a directory, to a zip file archive. + + + + + This method is handy if you are adding things to zip archive and don't + want to bother distinguishing between directories or files. Any files are + added as single entries. A directory added through this method is added + recursively: all files and subdirectories contained within the directory + are added to the ZipFile. + + + + The name of the item may be a relative path or a fully-qualified + path. Remember, the items contained in ZipFile instance get written + to the disk only when you call or a similar + save method. + + + + The directory name used for the file within the archive is the same + as the directory name (potentially a relative path) specified in the + . + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + + + This method has two overloads. + + the name of the file or directory to add. + + The ZipEntry added. + + + + Adds an item, either a file or a directory, to a zip file archive, + explicitly specifying the directory path to be used in the archive. + + + + + If adding a directory, the add is recursive on all files and + subdirectories contained within it. + + + The name of the item may be a relative path or a fully-qualified path. + The item added by this call to the ZipFile is not read from the + disk nor written to the zip file archive until the application calls + Save() on the ZipFile. + + + + This version of the method allows the caller to explicitly specify the + directory path to be used in the archive, which would override the + "natural" path of the filesystem file. + + + + Encryption will be used on the file data if the Password has + been set on the ZipFile object, prior to calling this method. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + Thrown if the file or directory passed in does not exist. + + + the name of the file or directory to add. + + + + The name of the directory path to use within the zip archive. This path + need not refer to an extant directory in the current filesystem. If the + files within the zip are later extracted, this is the path used for the + extracted file. Passing null (Nothing in VB) will use the + path on the fileOrDirectoryName. Passing the empty string ("") will + insert the item at the root path within the archive. + + + + + + + + This example shows how to zip up a set of files into a flat hierarchy, + regardless of where in the filesystem the files originated. The resulting + zip archive will contain a toplevel directory named "flat", which itself + will contain files Readme.txt, MyProposal.docx, and Image1.jpg. A + subdirectory under "flat" called SupportFiles will contain all the files + in the "c:\SupportFiles" directory on disk. + + + String[] itemnames= { + "c:\\fixedContent\\Readme.txt", + "MyProposal.docx", + "c:\\SupportFiles", // a directory + "images\\Image1.jpg" + }; + + try + { + using (ZipFile zip = new ZipFile()) + { + for (int i = 1; i < itemnames.Length; i++) + { + // will add Files or Dirs, recurses and flattens subdirectories + zip.AddItem(itemnames[i],"flat"); + } + zip.Save(ZipToCreate); + } + } + catch (System.Exception ex1) + { + System.Console.Error.WriteLine("exception: {0}", ex1); + } + + + + Dim itemnames As String() = _ + New String() { "c:\fixedContent\Readme.txt", _ + "MyProposal.docx", _ + "SupportFiles", _ + "images\Image1.jpg" } + Try + Using zip As New ZipFile + Dim i As Integer + For i = 1 To itemnames.Length - 1 + ' will add Files or Dirs, recursing and flattening subdirectories. + zip.AddItem(itemnames(i), "flat") + Next i + zip.Save(ZipToCreate) + End Using + Catch ex1 As Exception + Console.Error.WriteLine("exception: {0}", ex1.ToString()) + End Try + + + The ZipEntry added. + + + + Adds a File to a Zip file archive. + + + + + This call collects metadata for the named file in the filesystem, + including the file attributes and the timestamp, and inserts that metadata + into the resulting ZipEntry. Only when the application calls Save() on + the ZipFile, does DotNetZip read the file from the filesystem and + then write the content to the zip file archive. + + + + This method will throw an exception if an entry with the same name already + exists in the ZipFile. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + In this example, three files are added to a Zip archive. The ReadMe.txt + file will be placed in the root of the archive. The .png file will be + placed in a folder within the zip called photos\personal. The pdf file + will be included into a folder within the zip called Desktop. + + + try + { + using (ZipFile zip = new ZipFile()) + { + zip.AddFile("c:\\photos\\personal\\7440-N49th.png"); + zip.AddFile("c:\\Desktop\\2008-Regional-Sales-Report.pdf"); + zip.AddFile("ReadMe.txt"); + + zip.Save("Package.zip"); + } + } + catch (System.Exception ex1) + { + System.Console.Error.WriteLine("exception: " + ex1); + } + + + + Try + Using zip As ZipFile = New ZipFile + zip.AddFile("c:\photos\personal\7440-N49th.png") + zip.AddFile("c:\Desktop\2008-Regional-Sales-Report.pdf") + zip.AddFile("ReadMe.txt") + zip.Save("Package.zip") + End Using + Catch ex1 As Exception + Console.Error.WriteLine("exception: {0}", ex1.ToString) + End Try + + + + This method has two overloads. + + + + + + + The name of the file to add. It should refer to a file in the filesystem. + The name of the file may be a relative path or a fully-qualified path. + + The ZipEntry corresponding to the File added. + + + + Adds a File to a Zip file archive, potentially overriding the path to be + used within the zip archive. + + + + + The file added by this call to the ZipFile is not written to the + zip file archive until the application calls Save() on the ZipFile. + + + + This method will throw an exception if an entry with the same name already + exists in the ZipFile. + + + + This version of the method allows the caller to explicitly specify the + directory path to be used in the archive. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + In this example, three files are added to a Zip archive. The ReadMe.txt + file will be placed in the root of the archive. The .png file will be + placed in a folder within the zip called images. The pdf file will be + included into a folder within the zip called files\docs, and will be + encrypted with the given password. + + + try + { + using (ZipFile zip = new ZipFile()) + { + // the following entry will be inserted at the root in the archive. + zip.AddFile("c:\\datafiles\\ReadMe.txt", ""); + // this image file will be inserted into the "images" directory in the archive. + zip.AddFile("c:\\photos\\personal\\7440-N49th.png", "images"); + // the following will result in a password-protected file called + // files\\docs\\2008-Regional-Sales-Report.pdf in the archive. + zip.Password = "EncryptMe!"; + zip.AddFile("c:\\Desktop\\2008-Regional-Sales-Report.pdf", "files\\docs"); + zip.Save("Archive.zip"); + } + } + catch (System.Exception ex1) + { + System.Console.Error.WriteLine("exception: {0}", ex1); + } + + + + Try + Using zip As ZipFile = New ZipFile + ' the following entry will be inserted at the root in the archive. + zip.AddFile("c:\datafiles\ReadMe.txt", "") + ' this image file will be inserted into the "images" directory in the archive. + zip.AddFile("c:\photos\personal\7440-N49th.png", "images") + ' the following will result in a password-protected file called + ' files\\docs\\2008-Regional-Sales-Report.pdf in the archive. + zip.Password = "EncryptMe!" + zip.AddFile("c:\Desktop\2008-Regional-Sales-Report.pdf", "files\documents") + zip.Save("Archive.zip") + End Using + Catch ex1 As Exception + Console.Error.WriteLine("exception: {0}", ex1) + End Try + + + + + + + + + The name of the file to add. The name of the file may be a relative path + or a fully-qualified path. + + + + Specifies a directory path to use to override any path in the fileName. + This path may, or may not, correspond to a real directory in the current + filesystem. If the files within the zip are later extracted, this is the + path used for the extracted file. Passing null (Nothing in + VB) will use the path on the fileName, if any. Passing the empty string + ("") will insert the item at the root path within the archive. + + + The ZipEntry corresponding to the file added. + + + + This method removes a collection of entries from the ZipFile. + + + + A collection of ZipEntry instances from this zip file to be removed. For + example, you can pass in an array of ZipEntry instances; or you can call + SelectEntries(), and then add or remove entries from that + ICollection<ZipEntry> (ICollection(Of ZipEntry) in VB), and pass + that ICollection to this method. + + + + + + + + This method removes a collection of entries from the ZipFile, by name. + + + + A collection of strings that refer to names of entries to be removed + from the ZipFile. For example, you can pass in an array or a + List of Strings that provide the names of entries to be removed. + + + + + + + + This method adds a set of files to the ZipFile. + + + + + Use this method to add a set of files to the zip archive, in one call. + For example, a list of files received from + System.IO.Directory.GetFiles() can be added to a zip archive in one + call. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to each + ZipEntry added. + + + + + The collection of names of the files to add. Each string should refer to a + file in the filesystem. The name of the file may be a relative path or a + fully-qualified path. + + + + This example shows how to create a zip file, and add a few files into it. + + String ZipFileToCreate = "archive1.zip"; + String DirectoryToZip = "c:\\reports"; + using (ZipFile zip = new ZipFile()) + { + // Store all files found in the top level directory, into the zip archive. + String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip); + zip.AddFiles(filenames); + zip.Save(ZipFileToCreate); + } + + + + Dim ZipFileToCreate As String = "archive1.zip" + Dim DirectoryToZip As String = "c:\reports" + Using zip As ZipFile = New ZipFile + ' Store all files found in the top level directory, into the zip archive. + Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip) + zip.AddFiles(filenames) + zip.Save(ZipFileToCreate) + End Using + + + + + + + + Adds or updates a set of files in the ZipFile. + + + + + Any files that already exist in the archive are updated. Any files that + don't yet exist in the archive are added. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to each + ZipEntry added. + + + + + The collection of names of the files to update. Each string should refer to a file in + the filesystem. The name of the file may be a relative path or a fully-qualified path. + + + + + + Adds a set of files to the ZipFile, using the + specified directory path in the archive. + + + + + Any directory structure that may be present in the + filenames contained in the list is "flattened" in the + archive. Each file in the list is added to the archive in + the specified top-level directory. + + + + For ZipFile properties including , , , , , , and , their respective values at the + time of this call will be applied to each ZipEntry added. + + + + + The names of the files to add. Each string should refer to + a file in the filesystem. The name of the file may be a + relative path or a fully-qualified path. + + + + Specifies a directory path to use to override any path in the file name. + Th is path may, or may not, correspond to a real directory in the current + filesystem. If the files within the zip are later extracted, this is the + path used for the extracted file. Passing null (Nothing in + VB) will use the path on each of the fileNames, if any. Passing + the empty string ("") will insert the item at the root path within the + archive. + + + + + + + Adds a set of files to the ZipFile, using the specified directory + path in the archive, and preserving the full directory structure in the + filenames. + + + + + + Think of the as a "root" or + base directory used in the archive for the files that get added. when + is true, the hierarchy of files + found in the filesystem will be placed, with the hierarchy intact, + starting at that root in the archive. When preserveDirHierarchy + is false, the path hierarchy of files is flattned, and the flattened + set of files gets placed in the root within the archive as specified in + directoryPathInArchive. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to each + ZipEntry added. + + + + + + The names of the files to add. Each string should refer to a file in the + filesystem. The name of the file may be a relative path or a + fully-qualified path. + + + + Specifies a directory path to use as a prefix for each entry name. + This path may, or may not, correspond to a real directory in the current + filesystem. If the files within the zip are later extracted, this is the + path used for the extracted file. Passing null (Nothing in + VB) will use the path on each of the fileNames, if any. Passing + the empty string ("") will insert the item at the root path within the + archive. + + + + whether the entries in the zip archive will reflect the directory + hierarchy that is present in the various filenames. For example, if + includes two paths, + \Animalia\Chordata\Mammalia\Info.txt and + \Plantae\Magnoliophyta\Dicotyledon\Info.txt, then calling this method + with = false will + result in an exception because of a duplicate entry name, while + calling this method with = + true will result in the full direcory paths being included in + the entries added to the ZipFile. + + + + + + Adds or updates a set of files to the ZipFile, using the specified + directory path in the archive. + + + + + + Any files that already exist in the archive are updated. Any files that + don't yet exist in the archive are added. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to each + ZipEntry added. + + + + + The names of the files to add or update. Each string should refer to a + file in the filesystem. The name of the file may be a relative path or a + fully-qualified path. + + + + Specifies a directory path to use to override any path in the file name. + This path may, or may not, correspond to a real directory in the current + filesystem. If the files within the zip are later extracted, this is the + path used for the extracted file. Passing null (Nothing in + VB) will use the path on each of the fileNames, if any. Passing + the empty string ("") will insert the item at the root path within the + archive. + + + + + + + Adds or Updates a File in a Zip file archive. + + + + + This method adds a file to a zip archive, or, if the file already exists + in the zip archive, this method Updates the content of that given filename + in the zip archive. The UpdateFile method might more accurately be + called "AddOrUpdateFile". + + + + Upon success, there is no way for the application to learn whether the file + was added versus updated. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + This example shows how to Update an existing entry in a zipfile. The first + call to UpdateFile adds the file to the newly-created zip archive. The + second call to UpdateFile updates the content for that file in the zip + archive. + + + using (ZipFile zip1 = new ZipFile()) + { + // UpdateFile might more accurately be called "AddOrUpdateFile" + zip1.UpdateFile("MyDocuments\\Readme.txt"); + zip1.UpdateFile("CustomerList.csv"); + zip1.Comment = "This zip archive has been created."; + zip1.Save("Content.zip"); + } + + using (ZipFile zip2 = ZipFile.Read("Content.zip")) + { + zip2.UpdateFile("Updates\\Readme.txt"); + zip2.Comment = "This zip archive has been updated: The Readme.txt file has been changed."; + zip2.Save(); + } + + + + Using zip1 As New ZipFile + ' UpdateFile might more accurately be called "AddOrUpdateFile" + zip1.UpdateFile("MyDocuments\Readme.txt") + zip1.UpdateFile("CustomerList.csv") + zip1.Comment = "This zip archive has been created." + zip1.Save("Content.zip") + End Using + + Using zip2 As ZipFile = ZipFile.Read("Content.zip") + zip2.UpdateFile("Updates\Readme.txt") + zip2.Comment = "This zip archive has been updated: The Readme.txt file has been changed." + zip2.Save + End Using + + + + + + + + + The name of the file to add or update. It should refer to a file in the + filesystem. The name of the file may be a relative path or a + fully-qualified path. + + + + The ZipEntry corresponding to the File that was added or updated. + + + + + Adds or Updates a File in a Zip file archive. + + + + + This method adds a file to a zip archive, or, if the file already exists + in the zip archive, this method Updates the content of that given filename + in the zip archive. + + + + This version of the method allows the caller to explicitly specify the + directory path to be used in the archive. The entry to be added or + updated is found by using the specified directory path, combined with the + basename of the specified filename. + + + + Upon success, there is no way for the application to learn if the file was + added versus updated. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + + + The name of the file to add or update. It should refer to a file in the + filesystem. The name of the file may be a relative path or a + fully-qualified path. + + + + Specifies a directory path to use to override any path in the + fileName. This path may, or may not, correspond to a real + directory in the current filesystem. If the files within the zip are + later extracted, this is the path used for the extracted file. Passing + null (Nothing in VB) will use the path on the + fileName, if any. Passing the empty string ("") will insert the + item at the root path within the archive. + + + + The ZipEntry corresponding to the File that was added or updated. + + + + + Add or update a directory in a zip archive. + + + + If the specified directory does not exist in the archive, then this method + is equivalent to calling AddDirectory(). If the specified + directory already exists in the archive, then this method updates any + existing entries, and adds any new entries. Any entries that are in the + zip archive but not in the specified directory, are left alone. In other + words, the contents of the zip file will be a union of the previous + contents and the new files. + + + + + + + + The path to the directory to be added to the zip archive, or updated in + the zip archive. + + + + The ZipEntry corresponding to the Directory that was added or updated. + + + + + Add or update a directory in the zip archive at the specified root + directory in the archive. + + + + If the specified directory does not exist in the archive, then this method + is equivalent to calling AddDirectory(). If the specified + directory already exists in the archive, then this method updates any + existing entries, and adds any new entries. Any entries that are in the + zip archive but not in the specified directory, are left alone. In other + words, the contents of the zip file will be a union of the previous + contents and the new files. + + + + + + + + The path to the directory to be added to the zip archive, or updated + in the zip archive. + + + + Specifies a directory path to use to override any path in the + directoryName. This path may, or may not, correspond to a real + directory in the current filesystem. If the files within the zip are + later extracted, this is the path used for the extracted file. Passing + null (Nothing in VB) will use the path on the + directoryName, if any. Passing the empty string ("") will insert + the item at the root path within the archive. + + + + The ZipEntry corresponding to the Directory that was added or updated. + + + + + Add or update a file or directory in the zip archive. + + + + + This is useful when the application is not sure or does not care if the + item to be added is a file or directory, and does not know or does not + care if the item already exists in the ZipFile. Calling this method + is equivalent to calling RemoveEntry() if an entry by the same name + already exists, followed calling by AddItem(). + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + + + the path to the file or directory to be added or updated. + + + + + Add or update a file or directory. + + + + + This method is useful when the application is not sure or does not care if + the item to be added is a file or directory, and does not know or does not + care if the item already exists in the ZipFile. Calling this method + is equivalent to calling RemoveEntry(), if an entry by that name + exists, and then calling AddItem(). + + + + This version of the method allows the caller to explicitly specify the + directory path to be used for the item being added to the archive. The + entry or entries that are added or updated will use the specified + DirectoryPathInArchive. Extracting the entry from the archive will + result in a file stored in that directory path. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + + + The path for the File or Directory to be added or updated. + + + Specifies a directory path to use to override any path in the + itemName. This path may, or may not, correspond to a real + directory in the current filesystem. If the files within the zip are + later extracted, this is the path used for the extracted file. Passing + null (Nothing in VB) will use the path on the + itemName, if any. Passing the empty string ("") will insert the + item at the root path within the archive. + + + + + Adds a named entry into the zip archive, taking content for the entry + from a string. + + + + Calling this method creates an entry using the given fileName and + directory path within the archive. There is no need for a file by the + given name to exist in the filesystem; the name is used within the zip + archive only. The content for the entry is encoded using the default text + encoding for the machine. + + + + The content of the file, should it be extracted from the zip. + + + + The name, including any path, to use for the entry within the archive. + + + The ZipEntry added. + + + + This example shows how to add an entry to the zipfile, using a string as + content for that entry. + + + string Content = "This string will be the content of the Readme.txt file in the zip archive."; + using (ZipFile zip1 = new ZipFile()) + { + zip1.AddFile("MyDocuments\\Resume.doc", "files"); + zip1.AddEntry("Readme.txt", Content); + zip1.Comment = "This zip file was created at " + System.DateTime.Now.ToString("G"); + zip1.Save("Content.zip"); + } + + + + Public Sub Run() + Dim Content As String = "This string will be the content of the Readme.txt file in the zip archive." + Using zip1 As ZipFile = New ZipFile + zip1.AddEntry("Readme.txt", Content) + zip1.AddFile("MyDocuments\Resume.doc", "files") + zip1.Comment = ("This zip file was created at " & DateTime.Now.ToString("G")) + zip1.Save("Content.zip") + End Using + End Sub + + + + + + Adds a named entry into the zip archive, taking content for the entry + from a string, and using the specified text encoding. + + + + + + Calling this method creates an entry using the given fileName and + directory path within the archive. There is no need for a file by the + given name to exist in the filesystem; the name is used within the zip + archive only. + + + + The content for the entry, a string value, is encoded using the given + text encoding. A BOM (byte-order-mark) is emitted into the file, if the + Encoding parameter is set for that. + + + + Most Encoding classes support a constructor that accepts a boolean, + indicating whether to emit a BOM or not. For example see . + + + + + + The name, including any path, to use within the archive for the entry. + + + + The content of the file, should it be extracted from the zip. + + + + The text encoding to use when encoding the string. Be aware: This is + distinct from the text encoding used to encode the fileName, as specified + in . + + + The ZipEntry added. + + + + + Create an entry in the ZipFile using the given Stream + as input. The entry will have the given filename. + + + + + + The application should provide an open, readable stream; in this case it + will be read during the call to or one of + its overloads. + + + + The passed stream will be read from its current position. If + necessary, callers should set the position in the stream before + calling AddEntry(). This might be appropriate when using this method + with a MemoryStream, for example. + + + + In cases where a large number of streams will be added to the + ZipFile, the application may wish to avoid maintaining all of the + streams open simultaneously. To handle this situation, the application + should use the + overload. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + This example adds a single entry to a ZipFile via a Stream. + + + + String zipToCreate = "Content.zip"; + String fileNameInArchive = "Content-From-Stream.bin"; + using (System.IO.Stream streamToRead = MyStreamOpener()) + { + using (ZipFile zip = new ZipFile()) + { + ZipEntry entry= zip.AddEntry(fileNameInArchive, streamToRead); + zip.AddFile("Readme.txt"); + zip.Save(zipToCreate); // the stream is read implicitly here + } + } + + + + Dim zipToCreate As String = "Content.zip" + Dim fileNameInArchive As String = "Content-From-Stream.bin" + Using streamToRead as System.IO.Stream = MyStreamOpener() + Using zip As ZipFile = New ZipFile() + Dim entry as ZipEntry = zip.AddEntry(fileNameInArchive, streamToRead) + zip.AddFile("Readme.txt") + zip.Save(zipToCreate) '' the stream is read implicitly, here + End Using + End Using + + + + + + + The name, including any path, which is shown in the zip file for the added + entry. + + + The input stream from which to grab content for the file + + The ZipEntry added. + + + + Add a ZipEntry for which content is written directly by the application. + + + + + When the application needs to write the zip entry data, use this + method to add the ZipEntry. For example, in the case that the + application wishes to write the XML representation of a DataSet into + a ZipEntry, the application can use this method to do so. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + About progress events: When using the WriteDelegate, DotNetZip does + not issue any SaveProgress events with EventType = + Saving_EntryBytesRead. (This is because it is the + application's code that runs in WriteDelegate - there's no way for + DotNetZip to know when to issue a EntryBytesRead event.) + Applications that want to update a progress bar or similar status + indicator should do so from within the WriteDelegate + itself. DotNetZip will issue the other SaveProgress events, + including + Saving_Started, + + Saving_BeforeWriteEntry, and + Saving_AfterWriteEntry. + + + + Note: When you use PKZip encryption, it's normally necessary to + compute the CRC of the content to be encrypted, before compressing or + encrypting it. Therefore, when using PKZip encryption with a + WriteDelegate, the WriteDelegate CAN BE called twice: once to compute + the CRC, and the second time to potentially compress and + encrypt. Surprising, but true. This is because PKWARE specified that + the encryption initialization data depends on the CRC. + If this happens, for each call of the delegate, your + application must stream the same entry data in its entirety. If your + application writes different data during the second call, it will + result in a corrupt zip file. + + + + The double-read behavior happens with all types of entries, not only + those that use WriteDelegate. It happens if you add an entry from a + filesystem file, or using a string, or a stream, or an opener/closer + pair. But in those cases, DotNetZip takes care of reading twice; in + the case of the WriteDelegate, the application code gets invoked + twice. Be aware. + + + + As you can imagine, this can cause performance problems for large + streams, and it can lead to correctness problems when you use a + WriteDelegate. This is a pretty big pitfall. There are two + ways to avoid it. First, and most preferred: don't use PKZIP + encryption. If you use the WinZip AES encryption, this problem + doesn't occur, because the encryption protocol doesn't require the CRC + up front. Second: if you do choose to use PKZIP encryption, write out + to a non-seekable stream (like standard output, or the + Response.OutputStream in an ASP.NET application). In this case, + DotNetZip will use an alternative encryption protocol that does not + rely on the CRC of the content. This also implies setting bit 3 in + the zip entry, which still presents problems for some zip tools. + + + + In the future I may modify DotNetZip to *always* use bit 3 when PKZIP + encryption is in use. This seems like a win overall, but there will + be some work involved. If you feel strongly about it, visit the + DotNetZip forums and vote up the Workitem + tracking this issue. + + + + + the name of the entry to add + the delegate which will write the entry content + the ZipEntry added + + + + This example shows an application filling a DataSet, then saving the + contents of that DataSet as XML, into a ZipEntry in a ZipFile, using an + anonymous delegate in C#. The DataSet XML is never saved to a disk file. + + + var c1= new System.Data.SqlClient.SqlConnection(connstring1); + var da = new System.Data.SqlClient.SqlDataAdapter() + { + SelectCommand= new System.Data.SqlClient.SqlCommand(strSelect, c1) + }; + + DataSet ds1 = new DataSet(); + da.Fill(ds1, "Invoices"); + + using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile()) + { + zip.AddEntry(zipEntryName, (name,stream) => ds1.WriteXml(stream) ); + zip.Save(zipFileName); + } + + + + + + This example uses an anonymous method in C# as the WriteDelegate to provide + the data for the ZipEntry. The example is a bit contrived - the + AddFile() method is a simpler way to insert the contents of a file + into an entry in a zip file. On the other hand, if there is some sort of + processing or transformation of the file contents required before writing, + the application could use the WriteDelegate to do it, in this way. + + + using (var input = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite )) + { + using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile()) + { + zip.AddEntry(zipEntryName, (name,output) => + { + byte[] buffer = new byte[BufferSize]; + int n; + while ((n = input.Read(buffer, 0, buffer.Length)) != 0) + { + // could transform the data here... + output.Write(buffer, 0, n); + // could update a progress bar here + } + }); + + zip.Save(zipFileName); + } + } + + + + + + This example uses a named delegate in VB to write data for the given + ZipEntry (VB9 does not have anonymous delegates). The example here is a bit + contrived - a simpler way to add the contents of a file to a ZipEntry is to + simply use the appropriate AddFile() method. The key scenario for + which the WriteDelegate makes sense is saving a DataSet, in XML + format, to the zip file. The DataSet can write XML to a stream, and the + WriteDelegate is the perfect place to write into the zip file. There may be + other data structures that can write to a stream, but cannot be read as a + stream. The WriteDelegate would be appropriate for those cases as + well. + + + Private Sub WriteEntry (ByVal name As String, ByVal output As Stream) + Using input As FileStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) + Dim n As Integer = -1 + Dim buffer As Byte() = New Byte(BufferSize){} + Do While n <> 0 + n = input.Read(buffer, 0, buffer.Length) + output.Write(buffer, 0, n) + Loop + End Using + End Sub + + Public Sub Run() + Using zip = New ZipFile + zip.AddEntry(zipEntryName, New WriteDelegate(AddressOf WriteEntry)) + zip.Save(zipFileName) + End Using + End Sub + + + + + + Add an entry, for which the application will provide a stream + containing the entry data, on a just-in-time basis. + + + + + In cases where the application wishes to open the stream that + holds the content for the ZipEntry, on a just-in-time basis, the + application can use this method. The application provides an + opener delegate that will be called by the DotNetZip library to + obtain a readable stream that can be read to get the bytes for + the given entry. Typically, this delegate opens a stream. + Optionally, the application can provide a closer delegate as + well, which will be called by DotNetZip when all bytes have been + read from the entry. + + + + These delegates are called from within the scope of the call to + ZipFile.Save(). + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + This example uses anonymous methods in C# to open and close the + source stream for the content for a zip entry. + + + using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile()) + { + zip.AddEntry(zipEntryName, + (name) => File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ), + (name, stream) => stream.Close() + ); + + zip.Save(zipFileName); + } + + + + + + + This example uses delegates in VB.NET to open and close the + the source stream for the content for a zip entry. VB 9.0 lacks + support for "Sub" lambda expressions, and so the CloseDelegate must + be an actual, named Sub. + + + + Function MyStreamOpener(ByVal entryName As String) As Stream + '' This simply opens a file. You probably want to do somethinig + '' more involved here: open a stream to read from a database, + '' open a stream on an HTTP connection, and so on. + Return File.OpenRead(entryName) + End Function + + Sub MyStreamCloser(entryName As String, stream As Stream) + stream.Close() + End Sub + + Public Sub Run() + Dim dirToZip As String = "fodder" + Dim zipFileToCreate As String = "Archive.zip" + Dim opener As OpenDelegate = AddressOf MyStreamOpener + Dim closer As CloseDelegate = AddressOf MyStreamCloser + Dim numFilestoAdd As Int32 = 4 + Using zip As ZipFile = New ZipFile + Dim i As Integer + For i = 0 To numFilesToAdd - 1 + zip.AddEntry(String.Format("content-{0:000}.txt"), opener, closer) + Next i + zip.Save(zipFileToCreate) + End Using + End Sub + + + + + the name of the entry to add + + the delegate that will be invoked by ZipFile.Save() to get the + readable stream for the given entry. ZipFile.Save() will call + read on this stream to obtain the data for the entry. This data + will then be compressed and written to the newly created zip + file. + + + the delegate that will be invoked to close the stream. This may + be null (Nothing in VB), in which case no call is makde to close + the stream. + + the ZipEntry added + + + + + Updates the given entry in the ZipFile, using the given + string as content for the ZipEntry. + + + + + + Calling this method is equivalent to removing the ZipEntry for + the given file name and directory path, if it exists, and then calling + . See the documentation for + that method for further explanation. The string content is encoded + using the default encoding for the machine. This encoding is distinct + from the encoding used for the filename itself. See + . + + + + + + The name, including any path, to use within the archive for the entry. + + + + The content of the file, should it be extracted from the zip. + + + The ZipEntry added. + + + + + Updates the given entry in the ZipFile, using the given string as + content for the ZipEntry. + + + + Calling this method is equivalent to removing the ZipEntry for the + given file name and directory path, if it exists, and then calling . See the + documentation for that method for further explanation. + + + + The name, including any path, to use within the archive for the entry. + + + + The content of the file, should it be extracted from the zip. + + + + The text encoding to use when encoding the string. Be aware: This is + distinct from the text encoding used to encode the filename. See . + + + The ZipEntry added. + + + + + Updates the given entry in the ZipFile, using the given delegate + as the source for content for the ZipEntry. + + + + Calling this method is equivalent to removing the ZipEntry for the + given file name and directory path, if it exists, and then calling . See the + documentation for that method for further explanation. + + + + The name, including any path, to use within the archive for the entry. + + + the delegate which will write the entry content. + + The ZipEntry added. + + + + + Updates the given entry in the ZipFile, using the given delegates + to open and close the stream that provides the content for the ZipEntry. + + + + Calling this method is equivalent to removing the ZipEntry for the + given file name and directory path, if it exists, and then calling . See the + documentation for that method for further explanation. + + + + The name, including any path, to use within the archive for the entry. + + + + the delegate that will be invoked to open the stream + + + the delegate that will be invoked to close the stream + + + The ZipEntry added or updated. + + + + + Updates the given entry in the ZipFile, using the given stream as + input, and the given filename and given directory Path. + + + + + Calling the method is equivalent to calling RemoveEntry() if an + entry by the same name already exists, and then calling AddEntry() + with the given fileName and stream. + + + + The stream must be open and readable during the call to + ZipFile.Save. You can dispense the stream on a just-in-time basis + using the property. Check the + documentation of that property for more information. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to the + ZipEntry added. + + + + + + + + + The name, including any path, to use within the archive for the entry. + + + The input stream from which to read file data. + The ZipEntry added. + + + + Add an entry into the zip archive using the given filename and + directory path within the archive, and the given content for the + file. No file is created in the filesystem. + + + The data to use for the entry. + + + The name, including any path, to use within the archive for the entry. + + + The ZipEntry added. + + + + Updates the given entry in the ZipFile, using the given byte + array as content for the entry. + + + + Calling this method is equivalent to removing the ZipEntry + for the given filename and directory path, if it exists, and then + calling . See the + documentation for that method for further explanation. + + + + The name, including any path, to use within the archive for the entry. + + + The content to use for the ZipEntry. + + The ZipEntry added. + + + + + Adds the contents of a filesystem directory to a Zip file archive. + + + + + + The name of the directory may be a relative path or a fully-qualified + path. Any files within the named directory are added to the archive. Any + subdirectories within the named directory are also added to the archive, + recursively. + + + + Top-level entries in the named directory will appear as top-level entries + in the zip archive. Entries in subdirectories in the named directory will + result in entries in subdirectories in the zip archive. + + + + If you want the entries to appear in a containing directory in the zip + archive itself, then you should call the AddDirectory() overload that + allows you to explicitly specify a directory path for use in the archive. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to each + ZipEntry added. + + + + + + + + + + This method has 2 overloads. + + The name of the directory to add. + The ZipEntry added. + + + + Adds the contents of a filesystem directory to a Zip file archive, + overriding the path to be used for entries in the archive. + + + + + The name of the directory may be a relative path or a fully-qualified + path. The add operation is recursive, so that any files or subdirectories + within the name directory are also added to the archive. + + + + Top-level entries in the named directory will appear as top-level entries + in the zip archive. Entries in subdirectories in the named directory will + result in entries in subdirectories in the zip archive. + + + + For ZipFile properties including , , , , , + , and , their + respective values at the time of this call will be applied to each + ZipEntry added. + + + + + + + In this code, calling the ZipUp() method with a value of "c:\reports" for + the directory parameter will result in a zip file structure in which all + entries are contained in a toplevel "reports" directory. + + + + public void ZipUp(string targetZip, string directory) + { + using (var zip = new ZipFile()) + { + zip.AddDirectory(directory, System.IO.Path.GetFileName(directory)); + zip.Save(targetZip); + } + } + + + + + + + + The name of the directory to add. + + + Specifies a directory path to use to override any path in the + DirectoryName. This path may, or may not, correspond to a real directory + in the current filesystem. If the zip is later extracted, this is the + path used for the extracted file or directory. Passing null + (Nothing in VB) or the empty string ("") will insert the items at + the root path within the archive. + + + The ZipEntry added. + + + + Creates a directory in the zip archive. + + + + + + Use this when you want to create a directory in the archive but there is + no corresponding filesystem representation for that directory. + + + + You will probably not need to do this in your code. One of the only times + you will want to do this is if you want an empty directory in the zip + archive. The reason: if you add a file to a zip archive that is stored + within a multi-level directory, all of the directory tree is implicitly + created in the zip archive. + + + + + + The name of the directory to create in the archive. + + The ZipEntry added. + + + + Checks a zip file to see if its directory is consistent. + + + + + + In cases of data error, the directory within a zip file can get out + of synch with the entries in the zip file. This method checks the + given zip file and returns true if this has occurred. + + + This method may take a long time to run for large zip files. + + + This method is not supported in the Reduced version of DotNetZip. + + + + Developers using COM can use the ComHelper.CheckZip(String) + method. + + + + + The filename to of the zip file to check. + + true if the named zip file checks OK. Otherwise, false. + + + + + + + Checks a zip file to see if its directory is consistent, + and optionally fixes the directory if necessary. + + + + + + In cases of data error, the directory within a zip file can get out of + synch with the entries in the zip file. This method checks the given + zip file, and returns true if this has occurred. It also optionally + fixes the zipfile, saving the fixed copy in Name_Fixed.zip. + + + + This method may take a long time to run for large zip files. It + will take even longer if the file actually needs to be fixed, and if + fixIfNecessary is true. + + + + This method is not supported in the Reduced version of DotNetZip. + + + + + The filename to of the zip file to check. + + If true, the method will fix the zip file if + necessary. + + + a TextWriter in which messages generated while checking will be written. + + + true if the named zip is OK; false if the file needs to be fixed. + + + + + + + Rewrite the directory within a zipfile. + + + + + + In cases of data error, the directory in a zip file can get out of + synch with the entries in the zip file. This method attempts to fix + the zip file if this has occurred. + + + This can take a long time for large zip files. + + This won't work if the zip file uses a non-standard + code page - neither IBM437 nor UTF-8. + + + This method is not supported in the Reduced or Compact Framework + versions of DotNetZip. + + + + Developers using COM can use the ComHelper.FixZipDirectory(String) + method. + + + + + The filename to of the zip file to fix. + + + + + + + Verify the password on a zip file. + + + + + Keep in mind that passwords in zipfiles are applied to + zip entries, not to the entire zip file. So testing a + zipfile for a particular password doesn't work in the + general case. On the other hand, it's often the case + that a single password will be used on all entries in a + zip file. This method works for that case. + + + There is no way to check a password without doing the + decryption. So this code decrypts and extracts the given + zipfile into + + + + The filename to of the zip file to fix. + + The password to check. + + a bool indicating whether the password matches. + + + + Provides a human-readable string with information about the ZipFile. + + + + + The information string contains 10 lines or so, about each ZipEntry, + describing whether encryption is in use, the compressed and uncompressed + length of the entry, the offset of the entry, and so on. As a result the + information string can be very long for zip files that contain many + entries. + + + This information is mostly useful for diagnostic purposes. + + + + + + Indicates whether to perform a full scan of the zip file when reading it. + + + + + + You almost never want to use this property. + + + + When reading a zip file, if this flag is true (True in + VB), the entire zip archive will be scanned and searched for entries. + For large archives, this can take a very, long time. The much more + efficient default behavior is to read the zip directory, which is + stored at the end of the zip file. But, in some cases the directory is + corrupted and you need to perform a full scan of the zip file to + determine the contents of the zip file. This property lets you do + that, when necessary. + + + + This flag is effective only when calling . Normally you would read a ZipFile with the + static ZipFile.Read + method. But you can't set the FullScan property on the + ZipFile instance when you use a static factory method like + ZipFile.Read. + + + + + + + This example shows how to read a zip file using the full scan approach, + and then save it, thereby producing a corrected zip file. + + + using (var zip = new ZipFile()) + { + zip.FullScan = true; + zip.Initialize(zipFileName); + zip.Save(newName); + } + + + + Using zip As New ZipFile + zip.FullScan = True + zip.Initialize(zipFileName) + zip.Save(newName) + End Using + + + + + + + Whether to sort the ZipEntries before saving the file. + + + + The default is false. If you have a large number of zip entries, the sort + alone can consume significant time. + + + + + using (var zip = new ZipFile()) + { + zip.AddFiles(filesToAdd); + zip.SortEntriesBeforeSaving = true; + zip.Save(name); + } + + + + Using zip As New ZipFile + zip.AddFiles(filesToAdd) + zip.SortEntriesBeforeSaving = True + zip.Save(name) + End Using + + + + + + + Indicates whether NTFS Reparse Points, like junctions, should be + traversed during calls to AddDirectory(). + + + + By default, calls to AddDirectory() will traverse NTFS reparse + points, like mounted volumes, and directory junctions. An example + of a junction is the "My Music" directory in Windows Vista. In some + cases you may not want DotNetZip to traverse those directories. In + that case, set this property to false. + + + + + using (var zip = new ZipFile()) + { + zip.AddDirectoryWillTraverseReparsePoints = false; + zip.AddDirectory(dirToZip,"fodder"); + zip.Save(zipFileToCreate); + } + + + + + + Size of the IO buffer used while saving. + + + + + + First, let me say that you really don't need to bother with this. It is + here to allow for optimizations that you probably won't make! It will work + fine if you don't set or get this property at all. Ok? + + + + Now that we have that out of the way, the fine print: This + property affects the size of the buffer that is used for I/O for each + entry contained in the zip file. When a file is read in to be compressed, + it uses a buffer given by the size here. When you update a zip file, the + data for unmodified entries is copied from the first zip file to the + other, through a buffer given by the size here. + + + + Changing the buffer size affects a few things: first, for larger buffer + sizes, the memory used by the ZipFile, obviously, will be larger + during I/O operations. This may make operations faster for very much + larger files. Last, for any given entry, when you use a larger buffer + there will be fewer progress events during I/O operations, because there's + one progress event generated for each time the buffer is filled and then + emptied. + + + + The default buffer size is 8k. Increasing the buffer size may speed + things up as you compress larger files. But there are no hard-and-fast + rules here, eh? You won't know til you test it. And there will be a + limit where ever larger buffers actually slow things down. So as I said + in the beginning, it's probably best if you don't set or get this property + at all. + + + + + + This example shows how you might set a large buffer size for efficiency when + dealing with zip entries that are larger than 1gb. + + using (ZipFile zip = new ZipFile()) + { + zip.SaveProgress += this.zip1_SaveProgress; + zip.AddDirectory(directoryToZip, ""); + zip.UseZip64WhenSaving = Zip64Option.Always; + zip.BufferSize = 65536*8; // 65536 * 8 = 512k + zip.Save(ZipFileToCreate); + } + + + + + + Size of the work buffer to use for the ZLIB codec during compression. + + + + + When doing ZLIB or Deflate compression, the library fills a buffer, + then passes it to the compressor for compression. Then the library + reads out the compressed bytes. This happens repeatedly until there + is no more uncompressed data to compress. This property sets the + size of the buffer that will be used for chunk-wise compression. In + order for the setting to take effect, your application needs to set + this property before calling one of the ZipFile.Save() + overloads. + + + Setting this affects the performance and memory efficiency of + compression and decompression. For larger files, setting this to a + larger size may improve compression performance, but the exact + numbers vary depending on available memory, the size of the streams + you are compressing, and a bunch of other variables. I don't have + good firm recommendations on how to set it. You'll have to test it + yourself. Or just leave it alone and accept the default. + + + + + + Indicates whether extracted files should keep their paths as + stored in the zip archive. + + + + + This property affects Extraction. It is not used when creating zip + archives. + + + + With this property set to false, the default, extracting entries + from a zip file will create files in the filesystem that have the full + path associated to the entry within the zip file. With this property set + to true, extracting entries from the zip file results in files + with no path: the folders are "flattened." + + + + An example: suppose the zip file contains entries /directory1/file1.txt and + /directory2/file2.txt. With FlattenFoldersOnExtract set to false, + the files created will be \directory1\file1.txt and \directory2\file2.txt. + With the property set to true, the files created are file1.txt and file2.txt. + + + + + + + The compression strategy to use for all entries. + + + + Set the Strategy used by the ZLIB-compatible compressor, when + compressing entries using the DEFLATE method. Different compression + strategies work better on different sorts of data. The strategy + parameter can affect the compression ratio and the speed of + compression but not the correctness of the compresssion. For more + information see Ionic.Zlib.CompressionStrategy. + + + + + The name of the ZipFile, on disk. + + + + + + When the ZipFile instance was created by reading an archive using + one of the ZipFile.Read methods, this property represents the name + of the zip file that was read. When the ZipFile instance was + created by using the no-argument constructor, this value is null + (Nothing in VB). + + + + If you use the no-argument constructor, and you then explicitly set this + property, when you call , this name will + specify the name of the zip file created. Doing so is equivalent to + calling . When instantiating a + ZipFile by reading from a stream or byte array, the Name + property remains null. When saving to a stream, the Name + property is implicitly set to null. + + + + + + Sets the compression level to be used for entries subsequently added to + the zip archive. + + + + + Varying the compression level used on entries can affect the + size-vs-speed tradeoff when compression and decompressing data streams + or files. + + + + As with some other properties on the ZipFile class, like , , and , setting this property on a ZipFile + instance will cause the specified CompressionLevel to be used on all + items that are subsequently added to the + ZipFile instance. If you set this property after you have added + items to the ZipFile, but before you have called Save(), + those items will not use the specified compression level. + + + + If you do not set this property, the default compression level is used, + which normally gives a good balance of compression efficiency and + compression speed. In some tests, using BestCompression can + double the time it takes to compress, while delivering just a small + increase in compression efficiency. This behavior will vary with the + type of data you compress. If you are in doubt, just leave this setting + alone, and accept the default. + + + + + + The compression method for the zipfile. + + + + By default, the compression method is CompressionMethod.Deflate. + + + + + + + A comment attached to the zip archive. + + + + + + This property is read/write. It allows the application to specify a + comment for the ZipFile, or read the comment for the + ZipFile. After setting this property, changes are only made + permanent when you call a Save() method. + + + + According to PKWARE's + zip specification, the comment is not encrypted, even if there is a + password set on the zip file. + + + + The specification does not describe how to indicate the encoding used + on a comment string. Many "compliant" zip tools and libraries use + IBM437 as the code page for comments; DotNetZip, too, follows that + practice. On the other hand, there are situations where you want a + Comment to be encoded with something else, for example using code page + 950 "Big-5 Chinese". To fill that need, DotNetZip will encode the + comment following the same procedure it follows for encoding + filenames: (a) if is + Never, it uses the default encoding (IBM437). (b) if is Always, it always uses the + alternate encoding (). (c) if is AsNecessary, it uses the + alternate encoding only if the default encoding is not sufficient for + encoding the comment - in other words if decoding the result does not + produce the original string. This decision is taken at the time of + the call to ZipFile.Save(). + + + + When creating a zip archive using this library, it is possible to change + the value of between each + entry you add, and between adding entries and the call to + Save(). Don't do this. It will likely result in a zip file that is + not readable by any tool or application. For best interoperability, leave + alone, or specify it only + once, before adding any entries to the ZipFile instance. + + + + + + + Specifies whether the Creation, Access, and Modified times for entries + added to the zip file will be emitted in “Windows format” + when the zip archive is saved. + + + + + An application creating a zip archive can use this flag to explicitly + specify that the file times for the entries should or should not be stored + in the zip archive in the format used by Windows. By default this flag is + true, meaning the Windows-format times are stored in the zip + archive. + + + + When adding an entry from a file or directory, the Creation (), Access (), and Modified () times for the given entry are + automatically set from the filesystem values. When adding an entry from a + stream or string, all three values are implicitly set to + DateTime.Now. Applications can also explicitly set those times by + calling . + + + + PKWARE's + zip specification describes multiple ways to format these times in a + zip file. One is the format Windows applications normally use: 100ns ticks + since January 1, 1601 UTC. The other is a format Unix applications typically + use: seconds since January 1, 1970 UTC. Each format can be stored in an + "extra field" in the zip entry when saving the zip archive. The former + uses an extra field with a Header Id of 0x000A, while the latter uses a + header ID of 0x5455, although you probably don't need to know that. + + + + Not all tools and libraries can interpret these fields. Windows + compressed folders is one that can read the Windows Format timestamps, + while I believe the Infozip + tools can read the Unix format timestamps. Some tools and libraries + may be able to read only one or the other. DotNetZip can read or write + times in either or both formats. + + + + The times stored are taken from , , and . + + + + The value set here applies to all entries subsequently added to the + ZipFile. + + + + This property is not mutually exclusive of the property. It is possible and + legal and valid to produce a zip file that contains timestamps encoded in + the Unix format as well as in the Windows format, in addition to the LastModified time attached to each + entry in the archive, a time that is always stored in "DOS format". And, + notwithstanding the names PKWare uses for these time formats, any of them + can be read and written by any computer, on any operating system. But, + there are no guarantees that a program running on Mac or Linux will + gracefully handle a zip file with "Windows" formatted times, or that an + application that does not use DotNetZip but runs on Windows will be able to + handle file times in Unix format. + + + + When in doubt, test. Sorry, I haven't got a complete list of tools and + which sort of timestamps they can use and will tolerate. If you get any + good information and would like to pass it on, please do so and I will + include that information in this documentation. + + + + + This example shows how to save a zip file that contains file timestamps + in a format normally used by Unix. + + using (var zip = new ZipFile()) + { + // produce a zip file the Mac will like + zip.EmitTimesInWindowsFormatWhenSaving = false; + zip.EmitTimesInUnixFormatWhenSaving = true; + zip.AddDirectory(directoryToZip, "files"); + zip.Save(outputFile); + } + + + + Using zip As New ZipFile + '' produce a zip file the Mac will like + zip.EmitTimesInWindowsFormatWhenSaving = False + zip.EmitTimesInUnixFormatWhenSaving = True + zip.AddDirectory(directoryToZip, "files") + zip.Save(outputFile) + End Using + + + + + + + + + Specifies whether the Creation, Access, and Modified times + for entries added to the zip file will be emitted in "Unix(tm) + format" when the zip archive is saved. + + + + + An application creating a zip archive can use this flag to explicitly + specify that the file times for the entries should or should not be stored + in the zip archive in the format used by Unix. By default this flag is + false, meaning the Unix-format times are not stored in the zip + archive. + + + + When adding an entry from a file or directory, the Creation (), Access (), and Modified () times for the given entry are + automatically set from the filesystem values. When adding an entry from a + stream or string, all three values are implicitly set to DateTime.Now. + Applications can also explicitly set those times by calling . + + + + PKWARE's + zip specification describes multiple ways to format these times in a + zip file. One is the format Windows applications normally use: 100ns ticks + since January 1, 1601 UTC. The other is a format Unix applications + typically use: seconds since January 1, 1970 UTC. Each format can be + stored in an "extra field" in the zip entry when saving the zip + archive. The former uses an extra field with a Header Id of 0x000A, while + the latter uses a header ID of 0x5455, although you probably don't need to + know that. + + + + Not all tools and libraries can interpret these fields. Windows + compressed folders is one that can read the Windows Format timestamps, + while I believe the Infozip + tools can read the Unix format timestamps. Some tools and libraries may be + able to read only one or the other. DotNetZip can read or write times in + either or both formats. + + + + The times stored are taken from , , and . + + + + This property is not mutually exclusive of the property. It is possible and + legal and valid to produce a zip file that contains timestamps encoded in + the Unix format as well as in the Windows format, in addition to the LastModified time attached to each + entry in the zip archive, a time that is always stored in "DOS + format". And, notwithstanding the names PKWare uses for these time + formats, any of them can be read and written by any computer, on any + operating system. But, there are no guarantees that a program running on + Mac or Linux will gracefully handle a zip file with "Windows" formatted + times, or that an application that does not use DotNetZip but runs on + Windows will be able to handle file times in Unix format. + + + + When in doubt, test. Sorry, I haven't got a complete list of tools and + which sort of timestamps they can use and will tolerate. If you get any + good information and would like to pass it on, please do so and I will + include that information in this documentation. + + + + + + + + + Indicates whether verbose output is sent to the during AddXxx() and + ReadXxx() operations. + + + + This is a synthetic property. It returns true if the is non-null. + + + + + Returns true if an entry by the given name exists in the ZipFile. + + + the name of the entry to find + true if an entry with the given name exists; otherwise false. + + + + + Indicates whether to perform case-sensitive matching on the filename when + retrieving entries in the zipfile via the string-based indexer. + + + + The default value is false, which means don't do case-sensitive + matching. In other words, retrieving zip["ReadMe.Txt"] is the same as + zip["readme.txt"]. It really makes sense to set this to true only + if you are not running on Windows, which has case-insensitive + filenames. But since this library is not built for non-Windows platforms, + in most cases you should just leave this property alone. + + + + + Indicates whether to ignore duplicate files (report only the first entry) + when loading a zipfile. + + + + The default value is false, which will try to make all files + available (duplicates will have a "copy" suffix appended to their name). + Setting this to true prior to using Initialize to read a + zipfile will prevent this and instead just ignore the duplicates. + + + + + Indicates whether to encode entry filenames and entry comments using Unicode + (UTF-8). + + + + + The + PKWare zip specification provides for encoding file names and file + comments in either the IBM437 code page, or in UTF-8. This flag selects + the encoding according to that specification. By default, this flag is + false, and filenames and comments are encoded into the zip file in the + IBM437 codepage. Setting this flag to true will specify that filenames + and comments that cannot be encoded with IBM437 will be encoded with + UTF-8. + + + + Zip files created with strict adherence to the PKWare specification with + respect to UTF-8 encoding can contain entries with filenames containing + any combination of Unicode characters, including the full range of + characters from Chinese, Latin, Hebrew, Greek, Cyrillic, and many other + alphabets. However, because at this time, the UTF-8 portion of the PKWare + specification is not broadly supported by other zip libraries and + utilities, such zip files may not be readable by your favorite zip tool or + archiver. In other words, interoperability will decrease if you set this + flag to true. + + + + In particular, Zip files created with strict adherence to the PKWare + specification with respect to UTF-8 encoding will not work well with + Explorer in Windows XP or Windows Vista, because Windows compressed + folders, as far as I know, do not support UTF-8 in zip files. Vista can + read the zip files, but shows the filenames incorrectly. Unpacking from + Windows Vista Explorer will result in filenames that have rubbish + characters in place of the high-order UTF-8 bytes. + + + + Also, zip files that use UTF-8 encoding will not work well with Java + applications that use the java.util.zip classes, as of v5.0 of the Java + runtime. The Java runtime does not correctly implement the PKWare + specification in this regard. + + + + As a result, we have the unfortunate situation that "correct" behavior by + the DotNetZip library with regard to Unicode encoding of filenames during + zip creation will result in zip files that are readable by strictly + compliant and current tools (for example the most recent release of the + commercial WinZip tool); but these zip files will not be readable by + various other tools or libraries, including Windows Explorer. + + + + The DotNetZip library can read and write zip files with UTF8-encoded + entries, according to the PKware spec. If you use DotNetZip for both + creating and reading the zip file, and you use UTF-8, there will be no + loss of information in the filenames. For example, using a self-extractor + created by this library will allow you to unpack files correctly with no + loss of information in the filenames. + + + + If you do not set this flag, it will remain false. If this flag is false, + your ZipFile will encode all filenames and comments using the + IBM437 codepage. This can cause "loss of information" on some filenames, + but the resulting zipfile will be more interoperable with other + utilities. As an example of the loss of information, diacritics can be + lost. The o-tilde character will be down-coded to plain o. The c with a + cedilla (Unicode 0xE7) used in Portugese will be downcoded to a c. + Likewise, the O-stroke character (Unicode 248), used in Danish and + Norwegian, will be down-coded to plain o. Chinese characters cannot be + represented in codepage IBM437; when using the default encoding, Chinese + characters in filenames will be represented as ?. These are all examples + of "information loss". + + + + The loss of information associated to the use of the IBM437 encoding is + inconvenient, and can also lead to runtime errors. For example, using + IBM437, any sequence of 4 Chinese characters will be encoded as ????. If + your application creates a ZipFile, then adds two files, each with + names of four Chinese characters each, this will result in a duplicate + filename exception. In the case where you add a single file with a name + containing four Chinese characters, calling Extract() on the entry that + has question marks in the filename will result in an exception, because + the question mark is not legal for use within filenames on Windows. These + are just a few examples of the problems associated to loss of information. + + + + This flag is independent of the encoding of the content within the entries + in the zip file. Think of the zip file as a container - it supports an + encoding. Within the container are other "containers" - the file entries + themselves. The encoding within those entries is independent of the + encoding of the zip archive container for those entries. + + + + Rather than specify the encoding in a binary fashion using this flag, an + application can specify an arbitrary encoding via the property. Setting the encoding + explicitly when creating zip archives will result in non-compliant zip + files that, curiously, are fairly interoperable. The challenge is, the + PKWare specification does not provide for a way to specify that an entry + in a zip archive uses a code page that is neither IBM437 nor UTF-8. + Therefore if you set the encoding explicitly when creating a zip archive, + you must take care upon reading the zip archive to use the same code page. + If you get it wrong, the behavior is undefined and may result in incorrect + filenames, exceptions, stomach upset, hair loss, and acne. + + + + + + + Specify whether to use ZIP64 extensions when saving a zip archive. + + + + + + When creating a zip file, the default value for the property is . is + safest, in the sense that you will not get an Exception if a pre-ZIP64 + limit is exceeded. + + + + You may set the property at any time before calling Save(). + + + + When reading a zip file via the Zipfile.Read() method, DotNetZip + will properly read ZIP64-endowed zip archives, regardless of the value of + this property. DotNetZip will always read ZIP64 archives. This property + governs only whether DotNetZip will write them. Therefore, when updating + archives, be careful about setting this property after reading an archive + that may use ZIP64 extensions. + + + + An interesting question is, if you have set this property to + AsNecessary, and then successfully saved, does the resulting + archive use ZIP64 extensions or not? To learn this, check the property, after calling Save(). + + + + Have you thought about + donating? + + + + + + + + Indicates whether the archive requires ZIP64 extensions. + + + + + + This property is null (or Nothing in VB) if the archive has + not been saved, and there are fewer than 65334 ZipEntry items + contained in the archive. + + + + The Value is true if any of the following four conditions holds: + the uncompressed size of any entry is larger than 0xFFFFFFFF; the + compressed size of any entry is larger than 0xFFFFFFFF; the relative + offset of any entry within the zip archive is larger than 0xFFFFFFFF; or + there are more than 65534 entries in the archive. (0xFFFFFFFF = + 4,294,967,295). The result may not be known until a Save() is attempted + on the zip archive. The Value of this + property may be set only AFTER one of the Save() methods has been called. + + + + If none of the four conditions holds, and the archive has been saved, then + the Value is false. + + + + A Value of false does not indicate that the zip archive, as saved, + does not use ZIP64. It merely indicates that ZIP64 is not required. An + archive may use ZIP64 even when not required if the property is set to , or if the property is set to and the output stream was not + seekable. Use the property to determine if + the most recent Save() method resulted in an archive that utilized + the ZIP64 extensions. + + + + + + + + + Indicates whether the most recent Save() operation used ZIP64 extensions. + + + + + The use of ZIP64 extensions within an archive is not always necessary, and + for interoperability concerns, it may be desired to NOT use ZIP64 if + possible. The property can be + set to use ZIP64 extensions only when necessary. In those cases, + Sometimes applications want to know whether a Save() actually used ZIP64 + extensions. Applications can query this read-only property to learn + whether ZIP64 has been used in a just-saved ZipFile. + + + + The value is null (or Nothing in VB) if the archive has not + been saved. + + + + Non-null values (HasValue is true) indicate whether ZIP64 + extensions were used during the most recent Save() operation. The + ZIP64 extensions may have been used as required by any particular entry + because of its uncompressed or compressed size, or because the archive is + larger than 4294967295 bytes, or because there are more than 65534 entries + in the archive, or because the UseZip64WhenSaving property was set + to , or because the + UseZip64WhenSaving property was set to and the output stream was not seekable. + The value of this property does not indicate the reason the ZIP64 + extensions were used. + + + + + + + + + Indicates whether the most recent Read() operation read a zip file that uses + ZIP64 extensions. + + + + This property will return null (Nothing in VB) if you've added an entry after reading + the zip file. + + + + + The text encoding to use when writing new entries to the ZipFile, + for those entries that cannot be encoded with the default (IBM437) + encoding; or, the text encoding that was used when reading the entries + from the ZipFile. + + + + + In its + zip specification, PKWare describes two options for encoding + filenames and comments: using IBM437 or UTF-8. But, some archiving tools + or libraries do not follow the specification, and instead encode + characters using the system default code page. For example, WinRAR when + run on a machine in Shanghai may encode filenames with the Big-5 Chinese + (950) code page. This behavior is contrary to the Zip specification, but + it occurs anyway. + + + + When using DotNetZip to write zip archives that will be read by one of + these other archivers, set this property to specify the code page to use + when encoding the and for each ZipEntry in the zip file, for + values that cannot be encoded with the default codepage for zip files, + IBM437. This is why this property is "provisional". In all cases, IBM437 + is used where possible, in other words, where no loss of data would + result. It is possible, therefore, to have a given entry with a + Comment encoded in IBM437 and a FileName encoded with the + specified "provisional" codepage. + + + + Be aware that a zip file created after you've explicitly set the property to a value other than + IBM437 may not be compliant to the PKWare specification, and may not be + readable by compliant archivers. On the other hand, many (most?) + archivers are non-compliant and can read zip files created in arbitrary + code pages. The trick is to use or specify the proper codepage when + reading the zip. + + + + When creating a zip archive using this library, it is possible to change + the value of between each + entry you add, and between adding entries and the call to + Save(). Don't do this. It will likely result in a zipfile that is + not readable. For best interoperability, either leave alone, or specify it only once, + before adding any entries to the ZipFile instance. There is one + exception to this recommendation, described later. + + + + When using an arbitrary, non-UTF8 code page for encoding, there is no + standard way for the creator application - whether DotNetZip, WinZip, + WinRar, or something else - to formally specify in the zip file which + codepage has been used for the entries. As a result, readers of zip files + are not able to inspect the zip file and determine the codepage that was + used for the entries contained within it. It is left to the application + or user to determine the necessary codepage when reading zip files encoded + this way. In other words, if you explicitly specify the codepage when you + create the zipfile, you must explicitly specify the same codepage when + reading the zipfile. + + + + The way you specify the code page to use when reading a zip file varies + depending on the tool or library you use to read the zip. In DotNetZip, + you use a ZipFile.Read() method that accepts an encoding parameter. It + isn't possible with Windows Explorer, as far as I know, to specify an + explicit codepage to use when reading a zip. If you use an incorrect + codepage when reading a zipfile, you will get entries with filenames that + are incorrect, and the incorrect filenames may even contain characters + that are not legal for use within filenames in Windows. Extracting entries + with illegal characters in the filenames will lead to exceptions. It's too + bad, but this is just the way things are with code pages in zip + files. Caveat Emptor. + + + + Example: Suppose you create a zipfile that contains entries with + filenames that have Danish characters. If you use equal to "iso-8859-1" (cp 28591), + the filenames will be correctly encoded in the zip. But, to read that + zipfile correctly, you have to specify the same codepage at the time you + read it. If try to read that zip file with Windows Explorer or another + application that is not flexible with respect to the codepage used to + decode filenames in zipfiles, you will get a filename like "Inf�.txt". + + + + When using DotNetZip to read a zip archive, and the zip archive uses an + arbitrary code page, you must specify the encoding to use before or when + the Zipfile is READ. This means you must use a ZipFile.Read() + method that allows you to specify a System.Text.Encoding parameter. Setting + the ProvisionalAlternateEncoding property after your application has read in + the zip archive will not affect the entry names of entries that have already + been read in. + + + + And now, the exception to the rule described above. One strategy for + specifying the code page for a given zip file is to describe the code page + in a human-readable form in the Zip comment. For example, the comment may + read "Entries in this archive are encoded in the Big5 code page". For + maximum interoperability, the zip comment in this case should be encoded + in the default, IBM437 code page. In this case, the zip comment is + encoded using a different page than the filenames. To do this, Specify + ProvisionalAlternateEncoding to your desired region-specific code + page, once before adding any entries, and then reset + ProvisionalAlternateEncoding to IBM437 before setting the property and calling Save(). + + + + + This example shows how to read a zip file using the Big-5 Chinese code page + (950), and extract each entry in the zip file. For this code to work as + desired, the Zipfile must have been created using the big5 code page + (CP950). This is typical, for example, when using WinRar on a machine with + CP950 set as the default code page. In that case, the names of entries + within the Zip archive will be stored in that code page, and reading the zip + archive must be done using that code page. If the application did not use + the correct code page in ZipFile.Read(), then names of entries within the + zip archive would not be correctly retrieved. + + using (var zip = ZipFile.Read(zipFileName, System.Text.Encoding.GetEncoding("big5"))) + { + // retrieve and extract an entry using a name encoded with CP950 + zip[MyDesiredEntry].Extract("unpack"); + } + + + + Using zip As ZipFile = ZipFile.Read(ZipToExtract, System.Text.Encoding.GetEncoding("big5")) + ' retrieve and extract an entry using a name encoded with CP950 + zip(MyDesiredEntry).Extract("unpack") + End Using + + + + DefaultEncoding + + + + A Text Encoding to use when encoding the filenames and comments for + all the ZipEntry items, during a ZipFile.Save() operation. + + + + Whether the encoding specified here is used during the save depends + on . + + + + + + A flag that tells if and when this instance should apply + AlternateEncoding to encode the filenames and comments associated to + of ZipEntry objects contained within this instance. + + + + + Gets or sets the TextWriter to which status messages are delivered + for the instance. + + + + If the TextWriter is set to a non-null value, then verbose output is sent + to the TextWriter during Add, Read, Save and + Extract operations. Typically, console applications might use + Console.Out and graphical or headless applications might use a + System.IO.StringWriter. The output of this is suitable for viewing + by humans. + + + + + In this example, a console application instantiates a ZipFile, then + sets the StatusMessageTextWriter to Console.Out. At that + point, all verbose status messages for that ZipFile are sent to the + console. + + + + using (ZipFile zip= ZipFile.Read(FilePath)) + { + zip.StatusMessageTextWriter= System.Console.Out; + // messages are sent to the console during extraction + zip.ExtractAll(); + } + + + + Using zip As ZipFile = ZipFile.Read(FilePath) + zip.StatusMessageTextWriter= System.Console.Out + 'Status Messages will be sent to the console during extraction + zip.ExtractAll() + End Using + + + + In this example, a Windows Forms application instantiates a + ZipFile, then sets the StatusMessageTextWriter to a + StringWriter. At that point, all verbose status messages for that + ZipFile are sent to the StringWriter. + + + + var sw = new System.IO.StringWriter(); + using (ZipFile zip= ZipFile.Read(FilePath)) + { + zip.StatusMessageTextWriter= sw; + zip.ExtractAll(); + } + Console.WriteLine("{0}", sw.ToString()); + + + + Dim sw as New System.IO.StringWriter + Using zip As ZipFile = ZipFile.Read(FilePath) + zip.StatusMessageTextWriter= sw + zip.ExtractAll() + End Using + 'Status Messages are now available in sw + + + + + + + Gets or sets the name for the folder to store the temporary file + this library writes when saving a zip archive. + + + + + This library will create a temporary file when saving a Zip archive to a + file. This file is written when calling one of the Save() methods + that does not save to a stream, or one of the SaveSelfExtractor() + methods. + + + + By default, the library will create the temporary file in the directory + specified for the file itself, via the property or via + the method. + + + + Setting this property allows applications to override this default + behavior, so that the library will create the temporary file in the + specified folder. For example, to have the library create the temporary + file in the current working directory, regardless where the ZipFile + is saved, specfy ".". To revert to the default behavior, set this + property to null (Nothing in VB). + + + + When setting the property to a non-null value, the folder specified must + exist; if it does not an exception is thrown. The application should have + write and delete permissions on the folder. The permissions are not + explicitly checked ahead of time; if the application does not have the + appropriate rights, an exception will be thrown at the time Save() + is called. + + + + There is no temporary file created when reading a zip archive. When + saving to a Stream, there is no temporary file created. For example, if + the application is an ASP.NET application and calls Save() + specifying the Response.OutputStream as the output stream, there is + no temporary file created. + + + + + Thrown when setting the property if the directory does not exist. + + + + + + Sets the password to be used on the ZipFile instance. + + + + + + When writing a zip archive, this password is applied to the entries, not + to the zip archive itself. It applies to any ZipEntry subsequently + added to the ZipFile, using one of the AddFile, + AddDirectory, AddEntry, or AddItem methods, etc. + When reading a zip archive, this property applies to any entry + subsequently extracted from the ZipFile using one of the Extract + methods on the ZipFile class. + + + + When writing a zip archive, keep this in mind: though the password is set + on the ZipFile object, according to the Zip spec, the "directory" of the + archive - in other words the list of entries or files contained in the archive - is + not encrypted with the password, or protected in any way. If you set the + Password property, the password actually applies to individual entries + that are added to the archive, subsequent to the setting of this property. + The list of filenames in the archive that is eventually created will + appear in clear text, but the contents of the individual files are + encrypted. This is how Zip encryption works. + + + + One simple way around this limitation is to simply double-wrap sensitive + filenames: Store the files in a zip file, and then store that zip file + within a second, "outer" zip file. If you apply a password to the outer + zip file, then readers will be able to see that the outer zip file + contains an inner zip file. But readers will not be able to read the + directory or file list of the inner zip file. + + + + If you set the password on the ZipFile, and then add a set of files + to the archive, then each entry is encrypted with that password. You may + also want to change the password between adding different entries. If you + set the password, add an entry, then set the password to null + (Nothing in VB), and add another entry, the first entry is + encrypted and the second is not. If you call AddFile(), then set + the Password property, then call ZipFile.Save, the file + added will not be password-protected, and no warning will be generated. + + + + When setting the Password, you may also want to explicitly set the property, to specify how to encrypt the entries added + to the ZipFile. If you set the Password to a non-null value and do not + set , then PKZip 2.0 ("Weak") encryption is used. + This encryption is relatively weak but is very interoperable. If you set + the password to a null value (Nothing in VB), Encryption is + reset to None. + + + + All of the preceding applies to writing zip archives, in other words when + you use one of the Save methods. To use this property when reading or an + existing ZipFile, do the following: set the Password property on the + ZipFile, then call one of the Extract() overloads on the . In this case, the entry is extracted using the + Password that is specified on the ZipFile instance. If you + have not set the Password property, then the password is + null, and the entry is extracted with no password. + + + + If you set the Password property on the ZipFile, then call + Extract() an entry that has not been encrypted with a password, the + password is not used for that entry, and the ZipEntry is extracted + as normal. In other words, the password is used only if necessary. + + + + The class also has a Password property. It takes precedence + over this property on the ZipFile. Typically, you would use the + per-entry Password when most entries in the zip archive use one password, + and a few entries use a different password. If all entries in the zip + file use the same password, then it is simpler to just set this property + on the ZipFile itself, whether creating a zip archive or extracting + a zip archive. + + + + + + + This example creates a zip file, using password protection for the + entries, and then extracts the entries from the zip file. When creating + the zip file, the Readme.txt file is not protected with a password, but + the other two are password-protected as they are saved. During extraction, + each file is extracted with the appropriate password. + + + // create a file with encryption + using (ZipFile zip = new ZipFile()) + { + zip.AddFile("ReadMe.txt"); + zip.Password= "!Secret1"; + zip.AddFile("MapToTheSite-7440-N49th.png"); + zip.AddFile("2008-Regional-Sales-Report.pdf"); + zip.Save("EncryptedArchive.zip"); + } + + // extract entries that use encryption + using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip")) + { + zip.Password= "!Secret1"; + zip.ExtractAll("extractDir"); + } + + + + + Using zip As New ZipFile + zip.AddFile("ReadMe.txt") + zip.Password = "123456!" + zip.AddFile("MapToTheSite-7440-N49th.png") + zip.Password= "!Secret1"; + zip.AddFile("2008-Regional-Sales-Report.pdf") + zip.Save("EncryptedArchive.zip") + End Using + + + ' extract entries that use encryption + Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip")) + zip.Password= "!Secret1" + zip.ExtractAll("extractDir") + End Using + + + + + + ZipFile.Encryption + ZipEntry.Password + + + + The action the library should take when extracting a file that already + exists. + + + + + This property affects the behavior of the Extract methods (one of the + Extract() or ExtractWithPassword() overloads), when + extraction would would overwrite an existing filesystem file. If you do + not set this property, the library throws an exception when extracting an + entry would overwrite an existing file. + + + + This property has no effect when extracting to a stream, or when the file + to be extracted does not already exist. + + + + + + + The action the library should take when an error is encountered while + opening or reading files as they are saved into a zip archive. + + + + + Errors can occur as a file is being saved to the zip archive. For + example, the File.Open may fail, or a File.Read may fail, because of + lock conflicts or other reasons. + + + + The first problem might occur after having called AddDirectory() on a + directory that contains a Clipper .dbf file; the file is locked by + Clipper and cannot be opened for read by another process. An example of + the second problem might occur when trying to zip a .pst file that is in + use by Microsoft Outlook. Outlook locks a range on the file, which allows + other processes to open the file, but not read it in its entirety. + + + + This property tells DotNetZip what you would like to do in the case of + these errors. The primary options are: ZipErrorAction.Throw to + throw an exception (this is the default behavior if you don't set this + property); ZipErrorAction.Skip to Skip the file for which there + was an error and continue saving; ZipErrorAction.Retry to Retry + the entry that caused the problem; or + ZipErrorAction.InvokeErrorEvent to invoke an event handler. + + + + This property is implicitly set to ZipErrorAction.InvokeErrorEvent + if you add a handler to the event. If you set + this property to something other than + ZipErrorAction.InvokeErrorEvent, then the ZipError + event is implicitly cleared. What it means is you can set one or the + other (or neither), depending on what you want, but you never need to set + both. + + + + As with some other properties on the ZipFile class, like , , and , setting this property on a ZipFile + instance will cause the specified ZipErrorAction to be used on all + items that are subsequently added to the + ZipFile instance. If you set this property after you have added + items to the ZipFile, but before you have called Save(), + those items will not use the specified error handling action. + + + + If you want to handle any errors that occur with any entry in the zip + file in the same way, then set this property once, before adding any + entries to the zip archive. + + + + If you set this property to ZipErrorAction.Skip and you'd like to + learn which files may have been skipped after a Save(), you can + set the on the ZipFile before + calling Save(). A message will be emitted into that writer for + each skipped file, if any. + + + + + + This example shows how to tell DotNetZip to skip any files for which an + error is generated during the Save(). + + Public Sub SaveZipFile() + Dim SourceFolder As String = "fodder" + Dim DestFile As String = "eHandler.zip" + Dim sw as New StringWriter + Using zipArchive As ZipFile = New ZipFile + ' Tell DotNetZip to skip any files for which it encounters an error + zipArchive.ZipErrorAction = ZipErrorAction.Skip + zipArchive.StatusMessageTextWriter = sw + zipArchive.AddDirectory(SourceFolder) + zipArchive.Save(DestFile) + End Using + ' examine sw here to see any messages + End Sub + + + + + + + + + + The Encryption to use for entries added to the ZipFile. + + + + + Set this when creating a zip archive, or when updating a zip archive. The + specified Encryption is applied to the entries subsequently added to the + ZipFile instance. Applications do not need to set the + Encryption property when reading or extracting a zip archive. + + + + If you set this to something other than EncryptionAlgorithm.None, you + will also need to set the . + + + + As with some other properties on the ZipFile class, like and , setting this + property on a ZipFile instance will cause the specified + EncryptionAlgorithm to be used on all items + that are subsequently added to the ZipFile instance. In other + words, if you set this property after you have added items to the + ZipFile, but before you have called Save(), those items will + not be encrypted or protected with a password in the resulting zip + archive. To get a zip archive with encrypted entries, set this property, + along with the property, before calling + AddFile, AddItem, or AddDirectory (etc.) on the + ZipFile instance. + + + + If you read a ZipFile, you can modify the Encryption on an + encrypted entry, only by setting the Encryption property on the + ZipEntry itself. Setting the Encryption property on the + ZipFile, once it has been created via a call to + ZipFile.Read(), does not affect entries that were previously read. + + + + For example, suppose you read a ZipFile, and there is an encrypted + entry. Setting the Encryption property on that ZipFile and + then calling Save() on the ZipFile does not update the + Encryption used for the entries in the archive. Neither is an + exception thrown. Instead, what happens during the Save() is that + all previously existing entries are copied through to the new zip archive, + with whatever encryption and password that was used when originally + creating the zip archive. Upon re-reading that archive, to extract + entries, applications should use the original password or passwords, if + any. + + + + Suppose an application reads a ZipFile, and there is an encrypted + entry. Setting the Encryption property on that ZipFile and + then adding new entries (via AddFile(), AddEntry(), etc) + and then calling Save() on the ZipFile does not update the + Encryption on any of the entries that had previously been in the + ZipFile. The Encryption property applies only to the + newly-added entries. + + + + + + + This example creates a zip archive that uses encryption, and then extracts + entries from the archive. When creating the zip archive, the ReadMe.txt + file is zipped without using a password or encryption. The other files + use encryption. + + + + // Create a zip archive with AES Encryption. + using (ZipFile zip = new ZipFile()) + { + zip.AddFile("ReadMe.txt"); + zip.Encryption= EncryptionAlgorithm.WinZipAes256; + zip.Password= "Top.Secret.No.Peeking!"; + zip.AddFile("7440-N49th.png"); + zip.AddFile("2008-Regional-Sales-Report.pdf"); + zip.Save("EncryptedArchive.zip"); + } + + // Extract a zip archive that uses AES Encryption. + // You do not need to specify the algorithm during extraction. + using (ZipFile zip = ZipFile.Read("EncryptedArchive.zip")) + { + zip.Password= "Top.Secret.No.Peeking!"; + zip.ExtractAll("extractDirectory"); + } + + + + ' Create a zip that uses Encryption. + Using zip As New ZipFile() + zip.Encryption= EncryptionAlgorithm.WinZipAes256 + zip.Password= "Top.Secret.No.Peeking!" + zip.AddFile("ReadMe.txt") + zip.AddFile("7440-N49th.png") + zip.AddFile("2008-Regional-Sales-Report.pdf") + zip.Save("EncryptedArchive.zip") + End Using + + ' Extract a zip archive that uses AES Encryption. + ' You do not need to specify the algorithm during extraction. + Using (zip as ZipFile = ZipFile.Read("EncryptedArchive.zip")) + zip.Password= "Top.Secret.No.Peeking!" + zip.ExtractAll("extractDirectory") + End Using + + + + + ZipFile.Password + ZipEntry.Encryption + + + + A callback that allows the application to specify the compression level + to use for entries subsequently added to the zip archive. + + + + + + With this callback, the DotNetZip library allows the application to + determine whether compression will be used, at the time of the + Save. This may be useful if the application wants to favor + speed over size, and wants to defer the decision until the time of + Save. + + + + Typically applications set the property on + the ZipFile or on each ZipEntry to determine the level of + compression used. This is done at the time the entry is added to the + ZipFile. Setting the property to + Ionic.Zlib.CompressionLevel.None means no compression will be used. + + + + This callback allows the application to defer the decision on the + CompressionLevel to use, until the time of the call to + ZipFile.Save(). The callback is invoked once per ZipEntry, + at the time the data for the entry is being written out as part of a + Save() operation. The application can use whatever criteria it + likes in determining the level to return. For example, an application may + wish that no .mp3 files should be compressed, because they are already + compressed and the extra compression is not worth the CPU time incurred, + and so can return None for all .mp3 entries. + + + + The library determines whether compression will be attempted for an entry + this way: If the entry is a zero length file, or a directory, no + compression is used. Otherwise, if this callback is set, it is invoked + and the CompressionLevel is set to the return value. If this + callback has not been set, then the previously set value for + CompressionLevel is used. + + + + + + + The maximum size of an output segment, when saving a split Zip file. + + + + Make sure you do not read from this field if you've set the value using + + + + Set this to a non-zero value before calling or to specify that the ZipFile should be saved as a + split archive, also sometimes called a spanned archive. Some also + call them multi-file archives. + + + + A split zip archive is saved in a set of discrete filesystem files, + rather than in a single file. This is handy when transmitting the + archive in email or some other mechanism that has a limit to the size of + each file. The first file in a split archive will be named + basename.z01, the second will be named basename.z02, and + so on. The final file is named basename.zip. According to the zip + specification from PKWare, the minimum value is 65536, for a 64k segment + size. The maximum number of segments allows in a split archive is 99. + + + + The value of this property determines the maximum size of a split + segment when writing a split archive. For example, suppose you have a + ZipFile that would save to a single file of 200k. If you set the + MaxOutputSegmentSize to 65536 before calling Save(), you + will get four distinct output files. On the other hand if you set this + property to 256k, then you will get a single-file archive for that + ZipFile. + + + + The size of each split output file will be as large as possible, up to + the maximum size set here. The zip specification requires that some data + fields in a zip archive may not span a split boundary, and an output + segment may be smaller than the maximum if necessary to avoid that + problem. Also, obviously the final segment of the archive may be smaller + than the maximum segment size. Segments will never be larger than the + value set with this property. + + + + You can save a split Zip file only when saving to a regular filesystem + file. It's not possible to save a split zip file as a self-extracting + archive, nor is it possible to save a split zip file to a stream. When + saving to a SFX or to a Stream, this property is ignored. + + + + About interoperability: Split or spanned zip files produced by DotNetZip + can be read by WinZip or PKZip, and vice-versa. Segmented zip files may + not be readable by other tools, if those other tools don't support zip + spanning or splitting. When in doubt, test. I don't believe Windows + Explorer can extract a split archive. + + + + This property has no effect when reading a split archive. You can read + a split archive in the normal way with DotNetZip. + + + + When saving a zip file, if you want a regular zip file rather than a + split zip file, don't set this property, or set it to Zero. + + + + If you read a split archive, with and + then subsequently call ZipFile.Save(), unless you set this + property before calling Save(), you will get a normal, + single-file archive. + + + + + + + + The maximum size of an output segment, when saving a split Zip file. + + + + If you set this value, make sure you do not accidently use in your code + + + + Set this to a non-zero value before calling or to specify that the ZipFile should be saved as a + split archive, also sometimes called a spanned archive. Some also + call them multi-file archives. + + + + A split zip archive is saved in a set of discrete filesystem files, + rather than in a single file. This is handy when transmitting the + archive in email or some other mechanism that has a limit to the size of + each file. The first file in a split archive will be named + basename.z01, the second will be named basename.z02, and + so on. The final file is named basename.zip. According to the zip + specification from PKWare, the minimum value is 65536, for a 64k segment + size. The maximum number of segments allows in a split archive is 99. + + + + The value of this property determines the maximum size of a split + segment when writing a split archive. For example, suppose you have a + ZipFile that would save to a single file of 200k. If you set the + MaxOutputSegmentSize to 65536 before calling Save(), you + will get four distinct output files. On the other hand if you set this + property to 256k, then you will get a single-file archive for that + ZipFile. + + + + The size of each split output file will be as large as possible, up to + the maximum size set here. The zip specification requires that some data + fields in a zip archive may not span a split boundary, and an output + segment may be smaller than the maximum if necessary to avoid that + problem. Also, obviously the final segment of the archive may be smaller + than the maximum segment size. Segments will never be larger than the + value set with this property. + + + + You can save a split Zip file only when saving to a regular filesystem + file. It's not possible to save a split zip file as a self-extracting + archive, nor is it possible to save a split zip file to a stream. When + saving to a SFX or to a Stream, this property is ignored. + + + + About interoperability: Split or spanned zip files produced by DotNetZip + can be read by WinZip or PKZip, and vice-versa. Segmented zip files may + not be readable by other tools, if those other tools don't support zip + spanning or splitting. When in doubt, test. I don't believe Windows + Explorer can extract a split archive. + + + + This property has no effect when reading a split archive. You can read + a split archive in the normal way with DotNetZip. + + + + When saving a zip file, if you want a regular zip file rather than a + split zip file, don't set this property, or set it to Zero. + + + + If you read a split archive, with and + then subsequently call ZipFile.Save(), unless you set this + property before calling Save(), you will get a normal, + single-file archive. + + + + + + + + Returns the number of segments used in the most recent Save() operation. + + + + This is normally zero, unless you have set the property. If you have set , and then you save a file, after the call to + Save() completes, you can read this value to learn the number of segments that + were created. + + + If you call Save("Archive.zip"), and it creates 5 segments, then you + will have filesystem files named Archive.z01, Archive.z02, Archive.z03, + Archive.z04, and Archive.zip, and the value of this property will be 5. + + + + + + + The size threshold for an entry, above which a parallel deflate is used. + + + + + + DotNetZip will use multiple threads to compress any ZipEntry, + if the entry is larger than the given size. Zero means "always + use parallel deflate", while -1 means "never use parallel + deflate". The default value for this property is 512k. Aside + from the special values of 0 and 1, the minimum value is 65536. + + + + If the entry size cannot be known before compression, as with a + read-forward stream, then Parallel deflate will never be + performed, unless the value of this property is zero. + + + + A parallel deflate operations will speed up the compression of + large files, on computers with multiple CPUs or multiple CPU + cores. For files above 1mb, on a dual core or dual-cpu (2p) + machine, the time required to compress the file can be 70% of the + single-threaded deflate. For very large files on 4p machines the + compression can be done in 30% of the normal time. The downside + is that parallel deflate consumes extra memory during the deflate, + and the deflation is not as effective. + + + + Parallel deflate tends to yield slightly less compression when + compared to as single-threaded deflate; this is because the original + data stream is split into multiple independent buffers, each of which + is compressed in parallel. But because they are treated + independently, there is no opportunity to share compression + dictionaries. For that reason, a deflated stream may be slightly + larger when compressed using parallel deflate, as compared to a + traditional single-threaded deflate. Sometimes the increase over the + normal deflate is as much as 5% of the total compressed size. For + larger files it can be as small as 0.1%. + + + + Multi-threaded compression does not give as much an advantage when + using Encryption. This is primarily because encryption tends to slow + down the entire pipeline. Also, multi-threaded compression gives less + of an advantage when using lower compression levels, for example . You may have to + perform some tests to determine the best approach for your situation. + + + + + + + + + + The maximum number of buffer pairs to use when performing + parallel compression. + + + + + This property sets an upper limit on the number of memory + buffer pairs to create when performing parallel + compression. The implementation of the parallel + compression stream allocates multiple buffers to + facilitate parallel compression. As each buffer fills up, + the stream uses + ThreadPool.QueueUserWorkItem() to compress those + buffers in a background threadpool thread. After a buffer + is compressed, it is re-ordered and written to the output + stream. + + + + A higher number of buffer pairs enables a higher degree of + parallelism, which tends to increase the speed of compression on + multi-cpu computers. On the other hand, a higher number of buffer + pairs also implies a larger memory consumption, more active worker + threads, and a higher cpu utilization for any compression. This + property enables the application to limit its memory consumption and + CPU utilization behavior depending on requirements. + + + + For each compression "task" that occurs in parallel, there are 2 + buffers allocated: one for input and one for output. This property + sets a limit for the number of pairs. The total amount of storage + space allocated for buffering will then be (N*S*2), where N is the + number of buffer pairs, S is the size of each buffer (). By default, DotNetZip allocates 4 buffer + pairs per CPU core, so if your machine has 4 cores, and you retain + the default buffer size of 128k, then the + ParallelDeflateOutputStream will use 4 * 4 * 2 * 128kb of buffer + memory in total, or 4mb, in blocks of 128kb. If you then set this + property to 8, then the number will be 8 * 2 * 128kb of buffer + memory, or 2mb. + + + + CPU utilization will also go up with additional buffers, because a + larger number of buffer pairs allows a larger number of background + threads to compress in parallel. If you find that parallel + compression is consuming too much memory or CPU, you can adjust this + value downward. + + + + The default value is 16. Different values may deliver better or + worse results, depending on your priorities and the dynamic + performance characteristics of your storage and compute resources. + + + + This property is not the number of buffer pairs to use; it is an + upper limit. An illustration: Suppose you have an application that + uses the default value of this property (which is 16), and it runs + on a machine with 2 CPU cores. In that case, DotNetZip will allocate + 4 buffer pairs per CPU core, for a total of 8 pairs. The upper + limit specified by this property has no effect. + + + + The application can set this value at any time + before calling ZipFile.Save(). + + + + + + + + Provides a string representation of the instance. + a string representation of the instance. + + + + Returns the version number on the DotNetZip assembly. + + + + + This property is exposed as a convenience. Callers could also get the + version value by retrieving GetName().Version on the + System.Reflection.Assembly object pointing to the DotNetZip + assembly. But sometimes it is not clear which assembly is being loaded. + This property makes it clear. + + + This static property is primarily useful for diagnostic purposes. + + + + + + Creates a new ZipFile instance, using the specified filename. + + + + + Applications can use this constructor to create a new ZipFile for writing, + or to slurp in an existing zip archive for read and update purposes. + + + + To create a new zip archive, an application can call this constructor, + passing the name of a file that does not exist. The name may be a fully + qualified path. Then the application can add directories or files to the + ZipFile via AddDirectory(), AddFile(), AddItem() + and then write the zip archive to the disk by calling Save(). The + zip file is not actually opened and written to the disk until the + application calls ZipFile.Save(). At that point the new zip file + with the given name is created. + + + + If you won't know the name of the Zipfile until the time you call + ZipFile.Save(), or if you plan to save to a stream (which has no + name), then you should use the no-argument constructor. + + + + The application can also call this constructor to read an existing zip + archive. passing the name of a valid zip file that does exist. But, it's + better form to use the static method, + passing the name of the zip file, because using ZipFile.Read() in + your code communicates very clearly what you are doing. In either case, + the file is then read into the ZipFile instance. The app can then + enumerate the entries or can modify the zip file, for example adding + entries, removing entries, changing comments, and so on. + + + + One advantage to this parameterized constructor: it allows applications to + use the same code to add items to a zip archive, regardless of whether the + zip file exists. + + + + Instances of the ZipFile class are not multi-thread safe. You may + not party on a single instance with multiple threads. You may have + multiple threads that each use a distinct ZipFile instance, or you + can synchronize multi-thread access to a single instance. + + + + By the way, since DotNetZip is so easy to use, don't you think you should + donate $5 or $10? + + + + + + Thrown if name refers to an existing file that is not a valid zip file. + + + + This example shows how to create a zipfile, and add a few files into it. + + String ZipFileToCreate = "archive1.zip"; + String DirectoryToZip = "c:\\reports"; + using (ZipFile zip = new ZipFile()) + { + // Store all files found in the top level directory, into the zip archive. + String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip); + zip.AddFiles(filenames, "files"); + zip.Save(ZipFileToCreate); + } + + + + Dim ZipFileToCreate As String = "archive1.zip" + Dim DirectoryToZip As String = "c:\reports" + Using zip As ZipFile = New ZipFile() + Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip) + zip.AddFiles(filenames, "files") + zip.Save(ZipFileToCreate) + End Using + + + + The filename to use for the new zip archive. + + + + + Creates a new ZipFile instance, using the specified name for the + filename, and the specified Encoding. + + + + + See the documentation on the ZipFile + constructor that accepts a single string argument for basic + information on all the ZipFile constructors. + + + + The Encoding is used as the default alternate encoding for entries with + filenames or comments that cannot be encoded with the IBM437 code page. + This is equivalent to setting the property on the ZipFile + instance after construction. + + + + Instances of the ZipFile class are not multi-thread safe. You may + not party on a single instance with multiple threads. You may have + multiple threads that each use a distinct ZipFile instance, or you + can synchronize multi-thread access to a single instance. + + + + + + Thrown if name refers to an existing file that is not a valid zip file. + + + The filename to use for the new zip archive. + The Encoding is used as the default alternate + encoding for entries with filenames or comments that cannot be encoded + with the IBM437 code page. + + + + Create a zip file, without specifying a target filename or stream to save to. + + + + + See the documentation on the ZipFile + constructor that accepts a single string argument for basic + information on all the ZipFile constructors. + + + + After instantiating with this constructor and adding entries to the + archive, the application should call or + to save to a file or a + stream, respectively. The application can also set the + property and then call the no-argument method. (This + is the preferred approach for applications that use the library through + COM interop.) If you call the no-argument method + without having set the Name of the ZipFile, either through + the parameterized constructor or through the explicit property , the + Save() will throw, because there is no place to save the file. + + + Instances of the ZipFile class are not multi-thread safe. You may + have multiple threads that each use a distinct ZipFile instance, or + you can synchronize multi-thread access to a single instance. + + + + + This example creates a Zip archive called Backup.zip, containing all the files + in the directory DirectoryToZip. Files within subdirectories are not zipped up. + + using (ZipFile zip = new ZipFile()) + { + // Store all files found in the top level directory, into the zip archive. + // note: this code does not recurse subdirectories! + String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip); + zip.AddFiles(filenames, "files"); + zip.Save("Backup.zip"); + } + + + + Using zip As New ZipFile + ' Store all files found in the top level directory, into the zip archive. + ' note: this code does not recurse subdirectories! + Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip) + zip.AddFiles(filenames, "files") + zip.Save("Backup.zip") + End Using + + + + + + Create a zip file, specifying a text Encoding, but without specifying a + target filename or stream to save to. + + + + + See the documentation on the ZipFile + constructor that accepts a single string argument for basic + information on all the ZipFile constructors. + + + + + + The Encoding is used as the default alternate encoding for entries with + filenames or comments that cannot be encoded with the IBM437 code page. + + + + + Creates a new ZipFile instance, using the specified name for the + filename, and the specified status message writer. + + + + + See the documentation on the ZipFile + constructor that accepts a single string argument for basic + information on all the ZipFile constructors. + + + + This version of the constructor allows the caller to pass in a TextWriter, + to which verbose messages will be written during extraction or creation of + the zip archive. A console application may wish to pass + System.Console.Out to get messages on the Console. A graphical or headless + application may wish to capture the messages in a different + TextWriter, for example, a StringWriter, and then display + the messages in a TextBox, or generate an audit log of ZipFile operations. + + + + To encrypt the data for the files added to the ZipFile instance, + set the Password property after creating the ZipFile instance. + + + + Instances of the ZipFile class are not multi-thread safe. You may + not party on a single instance with multiple threads. You may have + multiple threads that each use a distinct ZipFile instance, or you + can synchronize multi-thread access to a single instance. + + + + + + Thrown if name refers to an existing file that is not a valid zip file. + + + + + using (ZipFile zip = new ZipFile("Backup.zip", Console.Out)) + { + // Store all files found in the top level directory, into the zip archive. + // note: this code does not recurse subdirectories! + // Status messages will be written to Console.Out + String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip); + zip.AddFiles(filenames); + zip.Save(); + } + + + + Using zip As New ZipFile("Backup.zip", Console.Out) + ' Store all files found in the top level directory, into the zip archive. + ' note: this code does not recurse subdirectories! + ' Status messages will be written to Console.Out + Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip) + zip.AddFiles(filenames) + zip.Save() + End Using + + + + The filename to use for the new zip archive. + A TextWriter to use for writing + verbose status messages. + + + + Creates a new ZipFile instance, using the specified name for the + filename, the specified status message writer, and the specified Encoding. + + + + + This constructor works like the ZipFile + constructor that accepts a single string argument. See that + reference for detail on what this constructor does. + + + + This version of the constructor allows the caller to pass in a + TextWriter, and an Encoding. The TextWriter will collect + verbose messages that are generated by the library during extraction or + creation of the zip archive. A console application may wish to pass + System.Console.Out to get messages on the Console. A graphical or + headless application may wish to capture the messages in a different + TextWriter, for example, a StringWriter, and then display + the messages in a TextBox, or generate an audit log of + ZipFile operations. + + + + The Encoding is used as the default alternate encoding for entries + with filenames or comments that cannot be encoded with the IBM437 code + page. This is a equivalent to setting the property on the ZipFile + instance after construction. + + + + To encrypt the data for the files added to the ZipFile instance, + set the Password property after creating the ZipFile + instance. + + + + Instances of the ZipFile class are not multi-thread safe. You may + not party on a single instance with multiple threads. You may have + multiple threads that each use a distinct ZipFile instance, or you + can synchronize multi-thread access to a single instance. + + + + + + Thrown if fileName refers to an existing file that is not a valid zip file. + + + The filename to use for the new zip archive. + A TextWriter to use for writing verbose + status messages. + + The Encoding is used as the default alternate encoding for entries with + filenames or comments that cannot be encoded with the IBM437 code page. + + + + + Initialize a ZipFile instance by reading in a zip file. + + + + + + This method is primarily useful from COM Automation environments, when + reading or extracting zip files. In COM, it is not possible to invoke + parameterized constructors for a class. A COM Automation application can + update a zip file by using the default (no argument) + constructor, then calling Initialize() to read the contents + of an on-disk zip archive into the ZipFile instance. + + + + .NET applications are encouraged to use the ZipFile.Read() methods + for better clarity. + + + + the name of the existing zip file to read in. + + + + This is an integer indexer into the Zip archive. + + + + + This property is read-only. + + + + Internally, the ZipEntry instances that belong to the + ZipFile are stored in a Dictionary. When you use this + indexer the first time, it creates a read-only + List<ZipEntry> from the Dictionary.Values Collection. + If at any time you modify the set of entries in the ZipFile, + either by adding an entry, removing an entry, or renaming an + entry, a new List will be created, and the numeric indexes for the + remaining entries may be different. + + + + This means you cannot rename any ZipEntry from + inside an enumeration of the zip file. + + + + The index value. + + + + + + The ZipEntry within the Zip archive at the specified index. If the + entry does not exist in the archive, this indexer throws. + + + + + + This is a name-based indexer into the Zip archive. + + + + + This property is read-only. + + + + The property on the ZipFile + determines whether retrieval via this indexer is done via case-sensitive + comparisons. By default, retrieval is not case sensitive. This makes + sense on Windows, in which filesystems are not case sensitive. + + + + Regardless of case-sensitivity, it is not always the case that + this[value].FileName == value. In other words, the FileName + property of the ZipEntry retrieved with this indexer, may or may + not be equal to the index value. + + + + This is because DotNetZip performs a normalization of filenames passed to + this indexer, before attempting to retrieve the item. That normalization + includes: removal of a volume letter and colon, swapping backward slashes + for forward slashes. So, zip["dir1\\entry1.txt"].FileName == + "dir1/entry.txt". + + + + Directory entries in the zip file may be retrieved via this indexer only + with names that have a trailing slash. DotNetZip automatically appends a + trailing slash to the names of any directory entries added to a zip. + + + + + + This example extracts only the entries in a zip file that are .txt files. + + using (ZipFile zip = ZipFile.Read("PackedDocuments.zip")) + { + foreach (string s1 in zip.EntryFilenames) + { + if (s1.EndsWith(".txt")) + zip[s1].Extract("textfiles"); + } + } + + + Using zip As ZipFile = ZipFile.Read("PackedDocuments.zip") + Dim s1 As String + For Each s1 In zip.EntryFilenames + If s1.EndsWith(".txt") Then + zip(s1).Extract("textfiles") + End If + Next + End Using + + + + + + Thrown if the caller attempts to assign a non-null value to the indexer. + + + + The name of the file, including any directory path, to retrieve from the + zip. The filename match is not case-sensitive by default; you can use the + property to change this behavior. The + pathname can use forward-slashes or backward slashes. + + + + The ZipEntry within the Zip archive, given by the specified + filename. If the named entry does not exist in the archive, this indexer + returns null (Nothing in VB). + + + + + + The list of filenames for the entries contained within the zip archive. + + + + According to the ZIP specification, the names of the entries use forward + slashes in pathnames. If you are scanning through the list, you may have + to swap forward slashes for backslashes. + + + + + + This example shows one way to test if a filename is already contained + within a zip archive. + + String zipFileToRead= "PackedDocuments.zip"; + string candidate = "DatedMaterial.xps"; + using (ZipFile zip = new ZipFile(zipFileToRead)) + { + if (zip.EntryFilenames.Contains(candidate)) + Console.WriteLine("The file '{0}' exists in the zip archive '{1}'", + candidate, + zipFileName); + else + Console.WriteLine("The file, '{0}', does not exist in the zip archive '{1}'", + candidate, + zipFileName); + Console.WriteLine(); + } + + + Dim zipFileToRead As String = "PackedDocuments.zip" + Dim candidate As String = "DatedMaterial.xps" + Using zip As ZipFile.Read(ZipFileToRead) + If zip.EntryFilenames.Contains(candidate) Then + Console.WriteLine("The file '{0}' exists in the zip archive '{1}'", _ + candidate, _ + zipFileName) + Else + Console.WriteLine("The file, '{0}', does not exist in the zip archive '{1}'", _ + candidate, _ + zipFileName) + End If + Console.WriteLine + End Using + + + + + The list of strings for the filenames contained within the Zip archive. + + + + + + Returns the readonly collection of entries in the Zip archive. + + + + + + If there are no entries in the current ZipFile, the value returned is a + non-null zero-element collection. If there are entries in the zip file, + the elements are returned in no particular order. + + + This is the implied enumerator on the ZipFile class. If you use a + ZipFile instance in a context that expects an enumerator, you will + get this collection. + + + + + + + Returns a readonly collection of entries in the Zip archive, sorted by FileName. + + + + If there are no entries in the current ZipFile, the value returned + is a non-null zero-element collection. If there are entries in the zip + file, the elements are returned sorted by the name of the entry. + + + + + This example fills a Windows Forms ListView with the entries in a zip file. + + + using (ZipFile zip = ZipFile.Read(zipFile)) + { + foreach (ZipEntry entry in zip.EntriesSorted) + { + ListViewItem item = new ListViewItem(n.ToString()); + n++; + string[] subitems = new string[] { + entry.FileName.Replace("/","\\"), + entry.LastModified.ToString("yyyy-MM-dd HH:mm:ss"), + entry.UncompressedSize.ToString(), + String.Format("{0,5:F0}%", entry.CompressionRatio), + entry.CompressedSize.ToString(), + (entry.UsesEncryption) ? "Y" : "N", + String.Format("{0:X8}", entry.Crc)}; + + foreach (String s in subitems) + { + ListViewItem.ListViewSubItem subitem = new ListViewItem.ListViewSubItem(); + subitem.Text = s; + item.SubItems.Add(subitem); + } + + this.listView1.Items.Add(item); + } + } + + + + + + + + Returns the number of entries in the Zip archive. + + + + + Removes the given ZipEntry from the zip archive. + + + + + After calling RemoveEntry, the application must call Save to + make the changes permanent. + + + + + Thrown if the specified ZipEntry does not exist in the ZipFile. + + + + In this example, all entries in the zip archive dating from before + December 31st, 2007, are removed from the archive. This is actually much + easier if you use the RemoveSelectedEntries method. But I needed an + example for RemoveEntry, so here it is. + + String ZipFileToRead = "ArchiveToModify.zip"; + System.DateTime Threshold = new System.DateTime(2007,12,31); + using (ZipFile zip = ZipFile.Read(ZipFileToRead)) + { + var EntriesToRemove = new System.Collections.Generic.List<ZipEntry>(); + foreach (ZipEntry e in zip) + { + if (e.LastModified < Threshold) + { + // We cannot remove the entry from the list, within the context of + // an enumeration of said list. + // So we add the doomed entry to a list to be removed later. + EntriesToRemove.Add(e); + } + } + + // actually remove the doomed entries. + foreach (ZipEntry zombie in EntriesToRemove) + zip.RemoveEntry(zombie); + + zip.Comment= String.Format("This zip archive was updated at {0}.", + System.DateTime.Now.ToString("G")); + + // save with a different name + zip.Save("Archive-Updated.zip"); + } + + + + Dim ZipFileToRead As String = "ArchiveToModify.zip" + Dim Threshold As New DateTime(2007, 12, 31) + Using zip As ZipFile = ZipFile.Read(ZipFileToRead) + Dim EntriesToRemove As New System.Collections.Generic.List(Of ZipEntry) + Dim e As ZipEntry + For Each e In zip + If (e.LastModified < Threshold) Then + ' We cannot remove the entry from the list, within the context of + ' an enumeration of said list. + ' So we add the doomed entry to a list to be removed later. + EntriesToRemove.Add(e) + End If + Next + + ' actually remove the doomed entries. + Dim zombie As ZipEntry + For Each zombie In EntriesToRemove + zip.RemoveEntry(zombie) + Next + zip.Comment = String.Format("This zip archive was updated at {0}.", DateTime.Now.ToString("G")) + 'save as a different name + zip.Save("Archive-Updated.zip") + End Using + + + + + The ZipEntry to remove from the zip. + + + + + + + + Removes the ZipEntry with the given filename from the zip archive. + + + + + After calling RemoveEntry, the application must call Save to + make the changes permanent. + + + + + + Thrown if the ZipFile is not updatable. + + + + Thrown if a ZipEntry with the specified filename does not exist in + the ZipFile. + + + + + This example shows one way to remove an entry with a given filename from + an existing zip archive. + + + String zipFileToRead= "PackedDocuments.zip"; + string candidate = "DatedMaterial.xps"; + using (ZipFile zip = ZipFile.Read(zipFileToRead)) + { + if (zip.EntryFilenames.Contains(candidate)) + { + zip.RemoveEntry(candidate); + zip.Comment= String.Format("The file '{0}' has been removed from this archive.", + Candidate); + zip.Save(); + } + } + + + Dim zipFileToRead As String = "PackedDocuments.zip" + Dim candidate As String = "DatedMaterial.xps" + Using zip As ZipFile = ZipFile.Read(zipFileToRead) + If zip.EntryFilenames.Contains(candidate) Then + zip.RemoveEntry(candidate) + zip.Comment = String.Format("The file '{0}' has been removed from this archive.", Candidate) + zip.Save + End If + End Using + + + + + The name of the file, including any directory path, to remove from the zip. + The filename match is not case-sensitive by default; you can use the + CaseSensitiveRetrieval property to change this behavior. The + pathname can use forward-slashes or backward slashes. + + + + + + Closes the read and write streams associated + to the ZipFile, if necessary. + + + + The Dispose() method is generally employed implicitly, via a using(..) {..} + statement. (Using...End Using in VB) If you do not employ a using + statement, insure that your application calls Dispose() explicitly. For + example, in a Powershell application, or an application that uses the COM + interop interface, you must call Dispose() explicitly. + + + + This example extracts an entry selected by name, from the Zip file to the + Console. + + using (ZipFile zip = ZipFile.Read(zipfile)) + { + foreach (ZipEntry e in zip) + { + if (WantThisEntry(e.FileName)) + zip.Extract(e.FileName, Console.OpenStandardOutput()); + } + } // Dispose() is called implicitly here. + + + + Using zip As ZipFile = ZipFile.Read(zipfile) + Dim e As ZipEntry + For Each e In zip + If WantThisEntry(e.FileName) Then + zip.Extract(e.FileName, Console.OpenStandardOutput()) + End If + Next + End Using ' Dispose is implicity called here + + + + + + Disposes any managed resources, if the flag is set, then marks the + instance disposed. This method is typically not called explicitly from + application code. + + + + Applications should call the no-arg Dispose method. + + + + indicates whether the method should dispose streams or not. + + + + + Default size of the buffer used for IO. + + + + + An event handler invoked when a Save() starts, before and after each + entry has been written to the archive, when a Save() completes, and + during other Save events. + + + + + Depending on the particular event, different properties on the parameter are set. The following + table summarizes the available EventTypes and the conditions under + which this event handler is invoked with a + SaveProgressEventArgs with the given EventType. + + + + + value of EntryType + Meaning and conditions + + + + ZipProgressEventType.Saving_Started + Fired when ZipFile.Save() begins. + + + + + ZipProgressEventType.Saving_BeforeSaveEntry + + Fired within ZipFile.Save(), just before writing data for each + particular entry. + + + + + ZipProgressEventType.Saving_AfterSaveEntry + + Fired within ZipFile.Save(), just after having finished writing data + for each particular entry. + + + + + ZipProgressEventType.Saving_Completed + Fired when ZipFile.Save() has completed. + + + + + ZipProgressEventType.Saving_AfterSaveTempArchive + + Fired after the temporary file has been created. This happens only + when saving to a disk file. This event will not be invoked when + saving to a stream. + + + + + ZipProgressEventType.Saving_BeforeRenameTempArchive + + Fired just before renaming the temporary file to the permanent + location. This happens only when saving to a disk file. This event + will not be invoked when saving to a stream. + + + + + ZipProgressEventType.Saving_AfterRenameTempArchive + + Fired just after renaming the temporary file to the permanent + location. This happens only when saving to a disk file. This event + will not be invoked when saving to a stream. + + + + + ZipProgressEventType.Saving_AfterCompileSelfExtractor + + Fired after a self-extracting archive has finished compiling. This + EventType is used only within SaveSelfExtractor(). + + + + + ZipProgressEventType.Saving_BytesRead + + Set during the save of a particular entry, to update progress of the + Save(). When this EventType is set, the BytesTransferred is the + number of bytes that have been read from the source stream. The + TotalBytesToTransfer is the number of bytes in the uncompressed + file. + + + + + + + + + This example uses an anonymous method to handle the + SaveProgress event, by updating a progress bar. + + + progressBar1.Value = 0; + progressBar1.Max = listbox1.Items.Count; + using (ZipFile zip = new ZipFile()) + { + // listbox1 contains a list of filenames + zip.AddFiles(listbox1.Items); + + // do the progress bar: + zip.SaveProgress += (sender, e) => { + if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry) { + progressBar1.PerformStep(); + } + }; + + zip.Save(fs); + } + + + + + This example uses a named method as the + SaveProgress event handler, to update the user, in a + console-based application. + + + static bool justHadByteUpdate= false; + public static void SaveProgress(object sender, SaveProgressEventArgs e) + { + if (e.EventType == ZipProgressEventType.Saving_Started) + Console.WriteLine("Saving: {0}", e.ArchiveName); + + else if (e.EventType == ZipProgressEventType.Saving_Completed) + { + justHadByteUpdate= false; + Console.WriteLine(); + Console.WriteLine("Done: {0}", e.ArchiveName); + } + + else if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry) + { + if (justHadByteUpdate) + Console.WriteLine(); + Console.WriteLine(" Writing: {0} ({1}/{2})", + e.CurrentEntry.FileName, e.EntriesSaved, e.EntriesTotal); + justHadByteUpdate= false; + } + + else if (e.EventType == ZipProgressEventType.Saving_EntryBytesRead) + { + if (justHadByteUpdate) + Console.SetCursorPosition(0, Console.CursorTop); + Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer, + e.BytesTransferred / (0.01 * e.TotalBytesToTransfer )); + justHadByteUpdate= true; + } + } + + public static ZipUp(string targetZip, string directory) + { + using (var zip = new ZipFile()) { + zip.SaveProgress += SaveProgress; + zip.AddDirectory(directory); + zip.Save(targetZip); + } + } + + + + + Public Sub ZipUp(ByVal targetZip As String, ByVal directory As String) + Using zip As ZipFile = New ZipFile + AddHandler zip.SaveProgress, AddressOf MySaveProgress + zip.AddDirectory(directory) + zip.Save(targetZip) + End Using + End Sub + + Private Shared justHadByteUpdate As Boolean = False + + Public Shared Sub MySaveProgress(ByVal sender As Object, ByVal e As SaveProgressEventArgs) + If (e.EventType Is ZipProgressEventType.Saving_Started) Then + Console.WriteLine("Saving: {0}", e.ArchiveName) + + ElseIf (e.EventType Is ZipProgressEventType.Saving_Completed) Then + justHadByteUpdate = False + Console.WriteLine + Console.WriteLine("Done: {0}", e.ArchiveName) + + ElseIf (e.EventType Is ZipProgressEventType.Saving_BeforeWriteEntry) Then + If justHadByteUpdate Then + Console.WriteLine + End If + Console.WriteLine(" Writing: {0} ({1}/{2})", e.CurrentEntry.FileName, e.EntriesSaved, e.EntriesTotal) + justHadByteUpdate = False + + ElseIf (e.EventType Is ZipProgressEventType.Saving_EntryBytesRead) Then + If justHadByteUpdate Then + Console.SetCursorPosition(0, Console.CursorTop) + End If + Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, _ + e.TotalBytesToTransfer, _ + (CDbl(e.BytesTransferred) / (0.01 * e.TotalBytesToTransfer))) + justHadByteUpdate = True + End If + End Sub + + + + + + This is a more complete example of using the SaveProgress + events in a Windows Forms application, with a + Thread object. + + + delegate void SaveEntryProgress(SaveProgressEventArgs e); + delegate void ButtonClick(object sender, EventArgs e); + + public class WorkerOptions + { + public string ZipName; + public string Folder; + public string Encoding; + public string Comment; + public int ZipFlavor; + public Zip64Option Zip64; + } + + private int _progress2MaxFactor; + private bool _saveCanceled; + private long _totalBytesBeforeCompress; + private long _totalBytesAfterCompress; + private Thread _workerThread; + + + private void btnZipup_Click(object sender, EventArgs e) + { + KickoffZipup(); + } + + private void btnCancel_Click(object sender, EventArgs e) + { + if (this.lblStatus.InvokeRequired) + { + this.lblStatus.Invoke(new ButtonClick(this.btnCancel_Click), new object[] { sender, e }); + } + else + { + _saveCanceled = true; + lblStatus.Text = "Canceled..."; + ResetState(); + } + } + + private void KickoffZipup() + { + _folderName = tbDirName.Text; + + if (_folderName == null || _folderName == "") return; + if (this.tbZipName.Text == null || this.tbZipName.Text == "") return; + + // check for existence of the zip file: + if (System.IO.File.Exists(this.tbZipName.Text)) + { + var dlgResult = MessageBox.Show(String.Format("The file you have specified ({0}) already exists." + + " Do you want to overwrite this file?", this.tbZipName.Text), + "Confirmation is Required", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (dlgResult != DialogResult.Yes) return; + System.IO.File.Delete(this.tbZipName.Text); + } + + _saveCanceled = false; + _nFilesCompleted = 0; + _totalBytesAfterCompress = 0; + _totalBytesBeforeCompress = 0; + this.btnOk.Enabled = false; + this.btnOk.Text = "Zipping..."; + this.btnCancel.Enabled = true; + lblStatus.Text = "Zipping..."; + + var options = new WorkerOptions + { + ZipName = this.tbZipName.Text, + Folder = _folderName, + Encoding = "ibm437" + }; + + if (this.comboBox1.SelectedIndex != 0) + { + options.Encoding = this.comboBox1.SelectedItem.ToString(); + } + + if (this.radioFlavorSfxCmd.Checked) + options.ZipFlavor = 2; + else if (this.radioFlavorSfxGui.Checked) + options.ZipFlavor = 1; + else options.ZipFlavor = 0; + + if (this.radioZip64AsNecessary.Checked) + options.Zip64 = Zip64Option.AsNecessary; + else if (this.radioZip64Always.Checked) + options.Zip64 = Zip64Option.Always; + else options.Zip64 = Zip64Option.Never; + + options.Comment = String.Format("Encoding:{0} || Flavor:{1} || ZIP64:{2}\r\nCreated at {3} || {4}\r\n", + options.Encoding, + FlavorToString(options.ZipFlavor), + options.Zip64.ToString(), + System.DateTime.Now.ToString("yyyy-MMM-dd HH:mm:ss"), + this.Text); + + if (this.tbComment.Text != TB_COMMENT_NOTE) + options.Comment += this.tbComment.Text; + + _workerThread = new Thread(this.DoSave); + _workerThread.Name = "Zip Saver thread"; + _workerThread.Start(options); + this.Cursor = Cursors.WaitCursor; + } + + + private void DoSave(Object p) + { + WorkerOptions options = p as WorkerOptions; + try + { + using (var zip1 = new ZipFile()) + { + zip1.ProvisionalAlternateEncoding = System.Text.Encoding.GetEncoding(options.Encoding); + zip1.Comment = options.Comment; + zip1.AddDirectory(options.Folder); + _entriesToZip = zip1.EntryFileNames.Count; + SetProgressBars(); + zip1.SaveProgress += this.zip1_SaveProgress; + + zip1.UseZip64WhenSaving = options.Zip64; + + if (options.ZipFlavor == 1) + zip1.SaveSelfExtractor(options.ZipName, SelfExtractorFlavor.WinFormsApplication); + else if (options.ZipFlavor == 2) + zip1.SaveSelfExtractor(options.ZipName, SelfExtractorFlavor.ConsoleApplication); + else + zip1.Save(options.ZipName); + } + } + catch (System.Exception exc1) + { + MessageBox.Show(String.Format("Exception while zipping: {0}", exc1.Message)); + btnCancel_Click(null, null); + } + } + + + + void zip1_SaveProgress(object sender, SaveProgressEventArgs e) + { + switch (e.EventType) + { + case ZipProgressEventType.Saving_AfterWriteEntry: + StepArchiveProgress(e); + break; + case ZipProgressEventType.Saving_EntryBytesRead: + StepEntryProgress(e); + break; + case ZipProgressEventType.Saving_Completed: + SaveCompleted(); + break; + case ZipProgressEventType.Saving_AfterSaveTempArchive: + // this event only occurs when saving an SFX file + TempArchiveSaved(); + break; + } + if (_saveCanceled) + e.Cancel = true; + } + + + + private void StepArchiveProgress(SaveProgressEventArgs e) + { + if (this.progressBar1.InvokeRequired) + { + this.progressBar1.Invoke(new SaveEntryProgress(this.StepArchiveProgress), new object[] { e }); + } + else + { + if (!_saveCanceled) + { + _nFilesCompleted++; + this.progressBar1.PerformStep(); + _totalBytesAfterCompress += e.CurrentEntry.CompressedSize; + _totalBytesBeforeCompress += e.CurrentEntry.UncompressedSize; + + // reset the progress bar for the entry: + this.progressBar2.Value = this.progressBar2.Maximum = 1; + + this.Update(); + } + } + } + + + private void StepEntryProgress(SaveProgressEventArgs e) + { + if (this.progressBar2.InvokeRequired) + { + this.progressBar2.Invoke(new SaveEntryProgress(this.StepEntryProgress), new object[] { e }); + } + else + { + if (!_saveCanceled) + { + if (this.progressBar2.Maximum == 1) + { + // reset + Int64 max = e.TotalBytesToTransfer; + _progress2MaxFactor = 0; + while (max > System.Int32.MaxValue) + { + max /= 2; + _progress2MaxFactor++; + } + this.progressBar2.Maximum = (int)max; + lblStatus.Text = String.Format("{0} of {1} files...({2})", + _nFilesCompleted + 1, _entriesToZip, e.CurrentEntry.FileName); + } + + int xferred = e.BytesTransferred >> _progress2MaxFactor; + + this.progressBar2.Value = (xferred >= this.progressBar2.Maximum) + ? this.progressBar2.Maximum + : xferred; + + this.Update(); + } + } + } + + private void SaveCompleted() + { + if (this.lblStatus.InvokeRequired) + { + this.lblStatus.Invoke(new MethodInvoker(this.SaveCompleted)); + } + else + { + lblStatus.Text = String.Format("Done, Compressed {0} files, {1:N0}% of original.", + _nFilesCompleted, (100.00 * _totalBytesAfterCompress) / _totalBytesBeforeCompress); + ResetState(); + } + } + + private void ResetState() + { + this.btnCancel.Enabled = false; + this.btnOk.Enabled = true; + this.btnOk.Text = "Zip it!"; + this.progressBar1.Value = 0; + this.progressBar2.Value = 0; + this.Cursor = Cursors.Default; + if (!_workerThread.IsAlive) + _workerThread.Join(); + } + + + + + + + + + + + An event handler invoked before, during, and after the reading of a zip archive. + + + + + Depending on the particular event being signaled, different properties on the + parameter are set. The following table + summarizes the available EventTypes and the conditions under which this + event handler is invoked with a ReadProgressEventArgs with the given EventType. + + + + + value of EntryType + Meaning and conditions + + + + ZipProgressEventType.Reading_Started + Fired just as ZipFile.Read() begins. Meaningful properties: ArchiveName. + + + + + ZipProgressEventType.Reading_Completed + Fired when ZipFile.Read() has completed. Meaningful properties: ArchiveName. + + + + + ZipProgressEventType.Reading_ArchiveBytesRead + Fired while reading, updates the number of bytes read for the entire archive. + Meaningful properties: ArchiveName, CurrentEntry, BytesTransferred, TotalBytesToTransfer. + + + + + ZipProgressEventType.Reading_BeforeReadEntry + Indicates an entry is about to be read from the archive. + Meaningful properties: ArchiveName, EntriesTotal. + + + + + ZipProgressEventType.Reading_AfterReadEntry + Indicates an entry has just been read from the archive. + Meaningful properties: ArchiveName, EntriesTotal, CurrentEntry. + + + + + + + + + + + + + An event handler invoked before, during, and after extraction of + entries in the zip archive. + + + + + Depending on the particular event, different properties on the parameter are set. The following + table summarizes the available EventTypes and the conditions under + which this event handler is invoked with a + ExtractProgressEventArgs with the given EventType. + + + + + value of EntryType + Meaning and conditions + + + + ZipProgressEventType.Extracting_BeforeExtractAll + + Set when ExtractAll() begins. The ArchiveName, Overwrite, and + ExtractLocation properties are meaningful. + + + + ZipProgressEventType.Extracting_AfterExtractAll + + Set when ExtractAll() has completed. The ArchiveName, Overwrite, + and ExtractLocation properties are meaningful. + + + + + ZipProgressEventType.Extracting_BeforeExtractEntry + + Set when an Extract() on an entry in the ZipFile has begun. + Properties that are meaningful: ArchiveName, EntriesTotal, + CurrentEntry, Overwrite, ExtractLocation, EntriesExtracted. + + + + + ZipProgressEventType.Extracting_AfterExtractEntry + + Set when an Extract() on an entry in the ZipFile has completed. + Properties that are meaningful: ArchiveName, EntriesTotal, + CurrentEntry, Overwrite, ExtractLocation, EntriesExtracted. + + + + + ZipProgressEventType.Extracting_EntryBytesWritten + + Set within a call to Extract() on an entry in the ZipFile, as data + is extracted for the entry. Properties that are meaningful: + ArchiveName, CurrentEntry, BytesTransferred, TotalBytesToTransfer. + + + + + ZipProgressEventType.Extracting_ExtractEntryWouldOverwrite + + Set within a call to Extract() on an entry in the ZipFile, when the + extraction would overwrite an existing file. This event type is used + only when ExtractExistingFileAction on the ZipFile or + ZipEntry is set to InvokeExtractProgressEvent. + + + + + + + + + + private static bool justHadByteUpdate = false; + public static void ExtractProgress(object sender, ExtractProgressEventArgs e) + { + if(e.EventType == ZipProgressEventType.Extracting_EntryBytesWritten) + { + if (justHadByteUpdate) + Console.SetCursorPosition(0, Console.CursorTop); + + Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer, + e.BytesTransferred / (0.01 * e.TotalBytesToTransfer )); + justHadByteUpdate = true; + } + else if(e.EventType == ZipProgressEventType.Extracting_BeforeExtractEntry) + { + if (justHadByteUpdate) + Console.WriteLine(); + Console.WriteLine("Extracting: {0}", e.CurrentEntry.FileName); + justHadByteUpdate= false; + } + } + + public static ExtractZip(string zipToExtract, string directory) + { + string TargetDirectory= "extract"; + using (var zip = ZipFile.Read(zipToExtract)) { + zip.ExtractProgress += ExtractProgress; + foreach (var e in zip1) + { + e.Extract(TargetDirectory, true); + } + } + } + + + + Public Shared Sub Main(ByVal args As String()) + Dim ZipToUnpack As String = "C1P3SML.zip" + Dim TargetDir As String = "ExtractTest_Extract" + Console.WriteLine("Extracting file {0} to {1}", ZipToUnpack, TargetDir) + Using zip1 As ZipFile = ZipFile.Read(ZipToUnpack) + AddHandler zip1.ExtractProgress, AddressOf MyExtractProgress + Dim e As ZipEntry + For Each e In zip1 + e.Extract(TargetDir, True) + Next + End Using + End Sub + + Private Shared justHadByteUpdate As Boolean = False + + Public Shared Sub MyExtractProgress(ByVal sender As Object, ByVal e As ExtractProgressEventArgs) + If (e.EventType = ZipProgressEventType.Extracting_EntryBytesWritten) Then + If ExtractTest.justHadByteUpdate Then + Console.SetCursorPosition(0, Console.CursorTop) + End If + Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer, (CDbl(e.BytesTransferred) / (0.01 * e.TotalBytesToTransfer))) + ExtractTest.justHadByteUpdate = True + ElseIf (e.EventType = ZipProgressEventType.Extracting_BeforeExtractEntry) Then + If ExtractTest.justHadByteUpdate Then + Console.WriteLine + End If + Console.WriteLine("Extracting: {0}", e.CurrentEntry.FileName) + ExtractTest.justHadByteUpdate = False + End If + End Sub + + + + + + + + + + An event handler invoked before, during, and after Adding entries to a zip archive. + + + + Adding a large number of entries to a zip file can take a long + time. For example, when calling on a + directory that contains 50,000 files, it could take 3 minutes or so. + This event handler allws an application to track the progress of the Add + operation, and to optionally cancel a lengthy Add operation. + + + + + + int _numEntriesToAdd= 0; + int _numEntriesAdded= 0; + void AddProgressHandler(object sender, AddProgressEventArgs e) + { + switch (e.EventType) + { + case ZipProgressEventType.Adding_Started: + Console.WriteLine("Adding files to the zip..."); + break; + case ZipProgressEventType.Adding_AfterAddEntry: + _numEntriesAdded++; + Console.WriteLine(String.Format("Adding file {0}/{1} :: {2}", + _numEntriesAdded, _numEntriesToAdd, e.CurrentEntry.FileName)); + break; + case ZipProgressEventType.Adding_Completed: + Console.WriteLine("Added all files"); + break; + } + } + + void CreateTheZip() + { + using (ZipFile zip = new ZipFile()) + { + zip.AddProgress += AddProgressHandler; + zip.AddDirectory(System.IO.Path.GetFileName(DirToZip)); + zip.Save(ZipFileToCreate); + } + } + + + + + + Private Sub AddProgressHandler(ByVal sender As Object, ByVal e As AddProgressEventArgs) + Select Case e.EventType + Case ZipProgressEventType.Adding_Started + Console.WriteLine("Adding files to the zip...") + Exit Select + Case ZipProgressEventType.Adding_AfterAddEntry + Console.WriteLine(String.Format("Adding file {0}", e.CurrentEntry.FileName)) + Exit Select + Case ZipProgressEventType.Adding_Completed + Console.WriteLine("Added all files") + Exit Select + End Select + End Sub + + Sub CreateTheZip() + Using zip as ZipFile = New ZipFile + AddHandler zip.AddProgress, AddressOf AddProgressHandler + zip.AddDirectory(System.IO.Path.GetFileName(DirToZip)) + zip.Save(ZipFileToCreate); + End Using + End Sub + + + + + + + + + + + + An event that is raised when an error occurs during open or read of files + while saving a zip archive. + + + + + Errors can occur as a file is being saved to the zip archive. For + example, the File.Open may fail, or a File.Read may fail, because of + lock conflicts or other reasons. If you add a handler to this event, + you can handle such errors in your own code. If you don't add a + handler, the library will throw an exception if it encounters an I/O + error during a call to Save(). + + + + Setting a handler implicitly sets to + ZipErrorAction.InvokeErrorEvent. + + + + The handler you add applies to all items that are + subsequently added to the ZipFile instance. If you set this + property after you have added items to the ZipFile, but before you + have called Save(), errors that occur while saving those items + will not cause the error handler to be invoked. + + + + If you want to handle any errors that occur with any entry in the zip + file using the same error handler, then add your error handler once, + before adding any entries to the zip archive. + + + + In the error handler method, you need to set the property on the + ZipErrorEventArgs.CurrentEntry. This communicates back to + DotNetZip what you would like to do with this particular error. Within + an error handler, if you set the ZipEntry.ZipErrorAction property + on the ZipEntry to ZipErrorAction.InvokeErrorEvent or if + you don't set it at all, the library will throw the exception. (It is the + same as if you had set the ZipEntry.ZipErrorAction property on the + ZipEntry to ZipErrorAction.Throw.) If you set the + ZipErrorEventArgs.Cancel to true, the entire Save() will be + canceled. + + + + In the case that you use ZipErrorAction.Skip, implying that + you want to skip the entry for which there's been an error, DotNetZip + tries to seek backwards in the output stream, and truncate all bytes + written on behalf of that particular entry. This works only if the + output stream is seekable. It will not work, for example, when using + ASPNET's Response.OutputStream. + + + + + + + This example shows how to use an event handler to handle + errors during save of the zip file. + + + public static void MyZipError(object sender, ZipErrorEventArgs e) + { + Console.WriteLine("Error saving {0}...", e.FileName); + Console.WriteLine(" Exception: {0}", e.exception); + ZipEntry entry = e.CurrentEntry; + string response = null; + // Ask the user whether he wants to skip this error or not + do + { + Console.Write("Retry, Skip, Throw, or Cancel ? (R/S/T/C) "); + response = Console.ReadLine(); + Console.WriteLine(); + + } while (response != null && + response[0]!='S' && response[0]!='s' && + response[0]!='R' && response[0]!='r' && + response[0]!='T' && response[0]!='t' && + response[0]!='C' && response[0]!='c'); + + e.Cancel = (response[0]=='C' || response[0]=='c'); + + if (response[0]=='S' || response[0]=='s') + entry.ZipErrorAction = ZipErrorAction.Skip; + else if (response[0]=='R' || response[0]=='r') + entry.ZipErrorAction = ZipErrorAction.Retry; + else if (response[0]=='T' || response[0]=='t') + entry.ZipErrorAction = ZipErrorAction.Throw; + } + + public void SaveTheFile() + { + string directoryToZip = "fodder"; + string directoryInArchive = "files"; + string zipFileToCreate = "Archive.zip"; + using (var zip = new ZipFile()) + { + // set the event handler before adding any entries + zip.ZipError += MyZipError; + zip.AddDirectory(directoryToZip, directoryInArchive); + zip.Save(zipFileToCreate); + } + } + + + + Private Sub MyZipError(ByVal sender As Object, ByVal e As Ionic.Zip.ZipErrorEventArgs) + ' At this point, the application could prompt the user for an action to take. + ' But in this case, this application will simply automatically skip the file, in case of error. + Console.WriteLine("Zip Error, entry {0}", e.CurrentEntry.FileName) + Console.WriteLine(" Exception: {0}", e.exception) + ' set the desired ZipErrorAction on the CurrentEntry to communicate that to DotNetZip + e.CurrentEntry.ZipErrorAction = Zip.ZipErrorAction.Skip + End Sub + + Public Sub SaveTheFile() + Dim directoryToZip As String = "fodder" + Dim directoryInArchive As String = "files" + Dim zipFileToCreate as String = "Archive.zip" + Using zipArchive As ZipFile = New ZipFile + ' set the event handler before adding any entries + AddHandler zipArchive.ZipError, AddressOf MyZipError + zipArchive.AddDirectory(directoryToZip, directoryInArchive) + zipArchive.Save(zipFileToCreate) + End Using + End Sub + + + + + + + + + Extracts all of the items in the zip archive, to the specified path in the + filesystem. The path can be relative or fully-qualified. + + + + + This method will extract all entries in the ZipFile to the + specified path. + + + + If an extraction of a file from the zip archive would overwrite an + existing file in the filesystem, the action taken is dictated by the + ExtractExistingFile property, which overrides any setting you may have + made on individual ZipEntry instances. By default, if you have not + set that property on the ZipFile instance, the entry will not + be extracted, the existing file will not be overwritten and an + exception will be thrown. To change this, set the property, or use the + overload that allows you to + specify an ExtractExistingFileAction parameter. + + + + The action to take when an extract would overwrite an existing file + applies to all entries. If you want to set this on a per-entry basis, + then you must use one of the ZipEntry.Extract methods. + + + + This method will send verbose output messages to the , if it is set on the ZipFile + instance. + + + + You may wish to take advantage of the ExtractProgress event. + + + + About timestamps: When extracting a file entry from a zip archive, the + extracted file gets the last modified time of the entry as stored in + the archive. The archive may also store extended file timestamp + information, including last accessed and created times. If these are + present in the ZipEntry, then the extracted file will also get + these times. + + + + A Directory entry is somewhat different. It will get the times as + described for a file entry, but, if there are file entries in the zip + archive that, when extracted, appear in the just-created directory, + then when those file entries are extracted, the last modified and last + accessed times of the directory will change, as a side effect. The + result is that after an extraction of a directory and a number of + files within the directory, the last modified and last accessed + timestamps on the directory will reflect the time that the last file + was extracted into the directory, rather than the time stored in the + zip archive for the directory. + + + + To compensate, when extracting an archive with ExtractAll, + DotNetZip will extract all the file and directory entries as described + above, but it will then make a second pass on the directories, and + reset the times on the directories to reflect what is stored in the + zip archive. + + + + This compensation is performed only within the context of an + ExtractAll. If you call ZipEntry.Extract on a directory + entry, the timestamps on directory in the filesystem will reflect the + times stored in the zip. If you then call ZipEntry.Extract on + a file entry, which is extracted into the directory, the timestamps on + the directory will be updated to the current time. + + + + + This example extracts all the entries in a zip archive file, to the + specified target directory. The extraction will overwrite any + existing files silently. + + + String TargetDirectory= "unpack"; + using(ZipFile zip= ZipFile.Read(ZipFileToExtract)) + { + zip.ExtractExistingFile= ExtractExistingFileAction.OverwriteSilently; + zip.ExtractAll(TargetDirectory); + } + + + + Dim TargetDirectory As String = "unpack" + Using zip As ZipFile = ZipFile.Read(ZipFileToExtract) + zip.ExtractExistingFile= ExtractExistingFileAction.OverwriteSilently + zip.ExtractAll(TargetDirectory) + End Using + + + + + + + + The path to which the contents of the zipfile will be extracted. + The path can be relative or fully-qualified. + + + + + + Extracts all of the items in the zip archive, to the specified path in the + filesystem, using the specified behavior when extraction would overwrite an + existing file. + + + + + + This method will extract all entries in the ZipFile to the specified + path. For an extraction that would overwrite an existing file, the behavior + is dictated by , which overrides any + setting you may have made on individual ZipEntry instances. + + + + The action to take when an extract would overwrite an existing file + applies to all entries. If you want to set this on a per-entry basis, + then you must use or one of the similar methods. + + + + Calling this method is equivalent to setting the property and then calling . + + + + This method will send verbose output messages to the + , if it is set on the ZipFile instance. + + + + + This example extracts all the entries in a zip archive file, to the + specified target directory. It does not overwrite any existing files. + + String TargetDirectory= "c:\\unpack"; + using(ZipFile zip= ZipFile.Read(ZipFileToExtract)) + { + zip.ExtractAll(TargetDirectory, ExtractExistingFileAction.DontOverwrite); + } + + + + Dim TargetDirectory As String = "c:\unpack" + Using zip As ZipFile = ZipFile.Read(ZipFileToExtract) + zip.ExtractAll(TargetDirectory, ExtractExistingFileAction.DontOverwrite) + End Using + + + + + The path to which the contents of the zipfile will be extracted. + The path can be relative or fully-qualified. + + + + The action to take if extraction would overwrite an existing file. + + + + + + Reads a zip file archive and returns the instance. + + + + + The stream is read using the default System.Text.Encoding, which is the + IBM437 codepage. + + + + + Thrown if the ZipFile cannot be read. The implementation of this method + relies on System.IO.File.OpenRead, which can throw a variety of exceptions, + including specific exceptions if a file is not found, an unauthorized access + exception, exceptions for poorly formatted filenames, and so on. + + + + The name of the zip archive to open. This can be a fully-qualified or relative + pathname. + + + . + + The instance read from the zip archive. + + + + + Reads a zip file archive from the named filesystem file using the + specified options. + + + + + This version of the Read() method allows the caller to pass + in a TextWriter an Encoding, via an instance of the + ReadOptions class. The ZipFile is read in using the + specified encoding for entries where UTF-8 encoding is not + explicitly specified. + + + + + + + This example shows how to read a zip file using the Big-5 Chinese + code page (950), and extract each entry in the zip file, while + sending status messages out to the Console. + + + + For this code to work as intended, the zipfile must have been + created using the big5 code page (CP950). This is typical, for + example, when using WinRar on a machine with CP950 set as the + default code page. In that case, the names of entries within the + Zip archive will be stored in that code page, and reading the zip + archive must be done using that code page. If the application did + not use the correct code page in ZipFile.Read(), then names of + entries within the zip archive would not be correctly retrieved. + + + + string zipToExtract = "MyArchive.zip"; + string extractDirectory = "extract"; + var options = new ReadOptions + { + StatusMessageWriter = System.Console.Out, + Encoding = System.Text.Encoding.GetEncoding(950) + }; + using (ZipFile zip = ZipFile.Read(zipToExtract, options)) + { + foreach (ZipEntry e in zip) + { + e.Extract(extractDirectory); + } + } + + + + + Dim zipToExtract as String = "MyArchive.zip" + Dim extractDirectory as String = "extract" + Dim options as New ReadOptions + options.Encoding = System.Text.Encoding.GetEncoding(950) + options.StatusMessageWriter = System.Console.Out + Using zip As ZipFile = ZipFile.Read(zipToExtract, options) + Dim e As ZipEntry + For Each e In zip + e.Extract(extractDirectory) + Next + End Using + + + + + + + + This example shows how to read a zip file using the default + code page, to remove entries that have a modified date before a given threshold, + sending status messages out to a StringWriter. + + + + var options = new ReadOptions + { + StatusMessageWriter = new System.IO.StringWriter() + }; + using (ZipFile zip = ZipFile.Read("PackedDocuments.zip", options)) + { + var Threshold = new DateTime(2007,7,4); + // We cannot remove the entry from the list, within the context of + // an enumeration of said list. + // So we add the doomed entry to a list to be removed later. + // pass 1: mark the entries for removal + var MarkedEntries = new System.Collections.Generic.List<ZipEntry>(); + foreach (ZipEntry e in zip) + { + if (e.LastModified < Threshold) + MarkedEntries.Add(e); + } + // pass 2: actually remove the entry. + foreach (ZipEntry zombie in MarkedEntries) + zip.RemoveEntry(zombie); + zip.Comment = "This archive has been updated."; + zip.Save(); + } + // can now use contents of sw, eg store in an audit log + + + + Dim options as New ReadOptions + options.StatusMessageWriter = New System.IO.StringWriter + Using zip As ZipFile = ZipFile.Read("PackedDocuments.zip", options) + Dim Threshold As New DateTime(2007, 7, 4) + ' We cannot remove the entry from the list, within the context of + ' an enumeration of said list. + ' So we add the doomed entry to a list to be removed later. + ' pass 1: mark the entries for removal + Dim MarkedEntries As New System.Collections.Generic.List(Of ZipEntry) + Dim e As ZipEntry + For Each e In zip + If (e.LastModified < Threshold) Then + MarkedEntries.Add(e) + End If + Next + ' pass 2: actually remove the entry. + Dim zombie As ZipEntry + For Each zombie In MarkedEntries + zip.RemoveEntry(zombie) + Next + zip.Comment = "This archive has been updated." + zip.Save + End Using + ' can now use contents of sw, eg store in an audit log + + + + + Thrown if the zipfile cannot be read. The implementation of + this method relies on System.IO.File.OpenRead, which + can throw a variety of exceptions, including specific + exceptions if a file is not found, an unauthorized access + exception, exceptions for poorly formatted filenames, and so + on. + + + + The name of the zip archive to open. + This can be a fully-qualified or relative pathname. + + + + The set of options to use when reading the zip file. + + + The ZipFile instance read from the zip archive. + + + + + + + Reads a zip file archive using the specified text encoding, the specified + TextWriter for status messages, and the specified ReadProgress event handler, + and returns the instance. + + + + The name of the zip archive to open. + This can be a fully-qualified or relative pathname. + + + + An event handler for Read operations. + + + + The System.IO.TextWriter to use for writing verbose status messages + during operations on the zip archive. A console application may wish to + pass System.Console.Out to get messages on the Console. A graphical + or headless application may wish to capture the messages in a different + TextWriter, such as a System.IO.StringWriter. + + + + The System.Text.Encoding to use when reading in the zip archive. Be + careful specifying the encoding. If the value you use here is not the same + as the Encoding used when the zip archive was created (possibly by a + different archiver) you will get unexpected results and possibly exceptions. + + + The instance read from the zip archive. + + + + + Reads a zip archive from a stream. + + + + + + When reading from a file, it's probably easier to just use + ZipFile.Read(String, ReadOptions). This + overload is useful when when the zip archive content is + available from an already-open stream. The stream must be + open and readable and seekable when calling this method. The + stream is left open when the reading is completed. + + + + Using this overload, the stream is read using the default + System.Text.Encoding, which is the IBM437 + codepage. If you want to specify the encoding to use when + reading the zipfile content, see + ZipFile.Read(Stream, ReadOptions). This + + + + Reading of zip content begins at the current position in the + stream. This means if you have a stream that concatenates + regular data and zip data, if you position the open, readable + stream at the start of the zip data, you will be able to read + the zip archive using this constructor, or any of the ZipFile + constructors that accept a as + input. Some examples of where this might be useful: the zip + content is concatenated at the end of a regular EXE file, as + some self-extracting archives do. (Note: SFX files produced + by DotNetZip do not work this way; they can be read as normal + ZIP files). Another example might be a stream being read from + a database, where the zip content is embedded within an + aggregate stream of data. + + + + + + + This example shows how to Read zip content from a stream, and + extract one entry into a different stream. In this example, + the filename "NameOfEntryInArchive.doc", refers only to the + name of the entry within the zip archive. A file by that + name is not created in the filesystem. The I/O is done + strictly with the given streams. + + + + using (ZipFile zip = ZipFile.Read(InputStream)) + { + zip.Extract("NameOfEntryInArchive.doc", OutputStream); + } + + + + Using zip as ZipFile = ZipFile.Read(InputStream) + zip.Extract("NameOfEntryInArchive.doc", OutputStream) + End Using + + + + the stream containing the zip data. + + The ZipFile instance read from the stream + + + + + Reads a zip file archive from the given stream using the + specified options. + + + + + + When reading from a file, it's probably easier to just use + ZipFile.Read(String, ReadOptions). This + overload is useful when when the zip archive content is + available from an already-open stream. The stream must be + open and readable and seekable when calling this method. The + stream is left open when the reading is completed. + + + + Reading of zip content begins at the current position in the + stream. This means if you have a stream that concatenates + regular data and zip data, if you position the open, readable + stream at the start of the zip data, you will be able to read + the zip archive using this constructor, or any of the ZipFile + constructors that accept a as + input. Some examples of where this might be useful: the zip + content is concatenated at the end of a regular EXE file, as + some self-extracting archives do. (Note: SFX files produced + by DotNetZip do not work this way; they can be read as normal + ZIP files). Another example might be a stream being read from + a database, where the zip content is embedded within an + aggregate stream of data. + + + + the stream containing the zip data. + + + The set of options to use when reading the zip file. + + + + Thrown if the zip archive cannot be read. + + + The ZipFile instance read from the stream. + + + + + + + Reads a zip archive from a stream, using the specified text Encoding, the + specified TextWriter for status messages, + and the specified ReadProgress event handler. + + + + + Reading of zip content begins at the current position in the stream. This + means if you have a stream that concatenates regular data and zip data, if + you position the open, readable stream at the start of the zip data, you + will be able to read the zip archive using this constructor, or any of the + ZipFile constructors that accept a as + input. Some examples of where this might be useful: the zip content is + concatenated at the end of a regular EXE file, as some self-extracting + archives do. (Note: SFX files produced by DotNetZip do not work this + way). Another example might be a stream being read from a database, where + the zip content is embedded within an aggregate stream of data. + + + + the stream containing the zip data. + + + The System.IO.TextWriter to which verbose status messages are written + during operations on the ZipFile. For example, in a console + application, System.Console.Out works, and will get a message for each entry + added to the ZipFile. If the TextWriter is null, no verbose messages + are written. + + + + The text encoding to use when reading entries that do not have the UTF-8 + encoding bit set. Be careful specifying the encoding. If the value you use + here is not the same as the Encoding used when the zip archive was created + (possibly by a different archiver) you will get unexpected results and + possibly exceptions. See the + property for more information. + + + + An event handler for Read operations. + + + an instance of ZipFile + + + + Checks the given file to see if it appears to be a valid zip file. + + + + + Calling this method is equivalent to calling with the testExtract parameter set to false. + + + + The file to check. + true if the file appears to be a zip file. + + + + Checks a file to see if it is a valid zip file. + + + + + This method opens the specified zip file, reads in the zip archive, + verifying the ZIP metadata as it reads. + + + + If everything succeeds, then the method returns true. If anything fails - + for example if an incorrect signature or CRC is found, indicating a + corrupt file, the the method returns false. This method also returns + false for a file that does not exist. + + + + If is true, as part of its check, this + method reads in the content for each entry, expands it, and checks CRCs. + This provides an additional check beyond verifying the zip header and + directory data. + + + + If is true, and if any of the zip entries + are protected with a password, this method will return false. If you want + to verify a ZipFile that has entries which are protected with a + password, you will need to do that manually. + + + + + The zip file to check. + true if the caller wants to extract each entry. + true if the file contains a valid zip file. + + + + Checks a stream to see if it contains a valid zip archive. + + + + + This method reads the zip archive contained in the specified stream, verifying + the ZIP metadata as it reads. If testExtract is true, this method also extracts + each entry in the archive, dumping all the bits into . + + + + If everything succeeds, then the method returns true. If anything fails - + for example if an incorrect signature or CRC is found, indicating a corrupt + file, the the method returns false. This method also returns false for a + file that does not exist. + + + + If testExtract is true, this method reads in the content for each + entry, expands it, and checks CRCs. This provides an additional check + beyond verifying the zip header data. + + + + If testExtract is true, and if any of the zip entries are protected + with a password, this method will return false. If you want to verify a + ZipFile that has entries which are protected with a password, you will need + to do that manually. + + + + + + The stream to check. + true if the caller wants to extract each entry. + true if the stream contains a valid zip archive. + + + + Delete file with retry on UnauthorizedAccessException. + + + + + When calling File.Delete() on a file that has been "recently" + created, the call sometimes fails with + UnauthorizedAccessException. This method simply retries the Delete 3 + times with a sleep between tries. + + + + the name of the file to be deleted + + + + Saves the Zip archive to a file, specified by the Name property of the + ZipFile. + + + + + The ZipFile instance is written to storage, typically a zip file + in a filesystem, only when the caller calls Save. In the typical + case, the Save operation writes the zip content to a temporary file, and + then renames the temporary file to the desired name. If necessary, this + method will delete a pre-existing file before the rename. + + + + The property is specified either explicitly, + or implicitly using one of the parameterized ZipFile constructors. For + COM Automation clients, the Name property must be set explicitly, + because COM Automation clients cannot call parameterized constructors. + + + + When using a filesystem file for the Zip output, it is possible to call + Save multiple times on the ZipFile instance. With each + call the zip content is re-written to the same output file. + + + + Data for entries that have been added to the ZipFile instance is + written to the output when the Save method is called. This means + that the input streams for those entries must be available at the time + the application calls Save. If, for example, the application + adds entries with AddEntry using a dynamically-allocated + MemoryStream, the memory stream must not have been disposed + before the call to Save. See the property for more discussion of the + availability requirements of the input stream for an entry, and an + approach for providing just-in-time stream lifecycle management. + + + + + + + + Thrown if you haven't specified a location or stream for saving the zip, + either in the constructor or by setting the Name property, or if you try + to save a regular zip archive to a filename with a .exe extension. + + + + Thrown if or is non-zero, and the number + of segments that would be generated for the spanned zip file during the + save operation exceeds 99. If this happens, you need to increase the + segment size. + + + + + + Save the file to a new zipfile, with the given name. + + + + + This method allows the application to explicitly specify the name of the zip + file when saving. Use this when creating a new zip file, or when + updating a zip archive. + + + + An application can also save a zip archive in several places by calling this + method multiple times in succession, with different filenames. + + + + The ZipFile instance is written to storage, typically a zip file in a + filesystem, only when the caller calls Save. The Save operation writes + the zip content to a temporary file, and then renames the temporary file + to the desired name. If necessary, this method will delete a pre-existing file + before the rename. + + + + + + Thrown if you specify a directory for the filename. + + + + The name of the zip archive to save to. Existing files will + be overwritten with great prejudice. + + + + This example shows how to create and Save a zip file. + + using (ZipFile zip = new ZipFile()) + { + zip.AddDirectory(@"c:\reports\January"); + zip.Save("January.zip"); + } + + + + Using zip As New ZipFile() + zip.AddDirectory("c:\reports\January") + zip.Save("January.zip") + End Using + + + + + + This example shows how to update a zip file. + + using (ZipFile zip = ZipFile.Read("ExistingArchive.zip")) + { + zip.AddFile("NewData.csv"); + zip.Save("UpdatedArchive.zip"); + } + + + + Using zip As ZipFile = ZipFile.Read("ExistingArchive.zip") + zip.AddFile("NewData.csv") + zip.Save("UpdatedArchive.zip") + End Using + + + + + + + Save the zip archive to the specified stream. + + + + + The ZipFile instance is written to storage - typically a zip file + in a filesystem, but using this overload, the storage can be anything + accessible via a writable stream - only when the caller calls Save. + + + + Use this method to save the zip content to a stream directly. A common + scenario is an ASP.NET application that dynamically generates a zip file + and allows the browser to download it. The application can call + Save(Response.OutputStream) to write a zipfile directly to the + output stream, without creating a zip file on the disk on the ASP.NET + server. + + + + Be careful when saving a file to a non-seekable stream, including + Response.OutputStream. When DotNetZip writes to a non-seekable + stream, the zip archive is formatted in such a way that may not be + compatible with all zip tools on all platforms. It's a perfectly legal + and compliant zip file, but some people have reported problems opening + files produced this way using the Mac OS archive utility. + + + + + + + This example saves the zipfile content into a MemoryStream, and + then gets the array of bytes from that MemoryStream. + + + using (var zip = new Ionic.Zip.ZipFile()) + { + zip.CompressionLevel= Ionic.Zlib.CompressionLevel.BestCompression; + zip.Password = "VerySecret."; + zip.Encryption = EncryptionAlgorithm.WinZipAes128; + zip.AddFile(sourceFileName); + MemoryStream output = new MemoryStream(); + zip.Save(output); + + byte[] zipbytes = output.ToArray(); + } + + + + + + This example shows a pitfall you should avoid. DO NOT read + from a stream, then try to save to the same stream. DO + NOT DO THIS: + + + + using (var fs = new FileStream(filename, FileMode.Open)) + { + using (var zip = Ionic.Zip.ZipFile.Read(inputStream)) + { + zip.AddEntry("Name1.txt", "this is the content"); + zip.Save(inputStream); // NO NO NO!! + } + } + + + + Better like this: + + + + using (var zip = Ionic.Zip.ZipFile.Read(filename)) + { + zip.AddEntry("Name1.txt", "this is the content"); + zip.Save(); // YES! + } + + + + + + The System.IO.Stream to write to. It must be + writable. If you created the ZipFile instance by calling + ZipFile.Read(), this stream must not be the same stream + you passed to ZipFile.Read(). + + + + + Adds to the ZipFile a set of files from the current working directory on + disk, that conform to the specified criteria. + + + + + This method selects files from the the current working directory matching + the specified criteria, and adds them to the ZipFile. + + + + Specify the criteria in statements of 3 elements: a noun, an operator, and + a value. Consider the string "name != *.doc" . The noun is "name". The + operator is "!=", implying "Not Equal". The value is "*.doc". That + criterion, in English, says "all files with a name that does not end in + the .doc extension." + + + + Supported nouns include "name" (or "filename") for the filename; "atime", + "mtime", and "ctime" for last access time, last modfied time, and created + time of the file, respectively; "attributes" (or "attrs") for the file + attributes; "size" (or "length") for the file length (uncompressed), and + "type" for the type of object, either a file or a directory. The + "attributes", "name" and "type" nouns both support = and != as operators. + The "size", "atime", "mtime", and "ctime" nouns support = and !=, and + >, >=, <, <= as well. The times are taken to be expressed in + local time. + + + + Specify values for the file attributes as a string with one or more of the + characters H,R,S,A,I,L in any order, implying file attributes of Hidden, + ReadOnly, System, Archive, NotContextIndexed, and ReparsePoint (symbolic + link) respectively. + + + + To specify a time, use YYYY-MM-DD-HH:mm:ss or YYYY/MM/DD-HH:mm:ss as the + format. If you omit the HH:mm:ss portion, it is assumed to be 00:00:00 + (midnight). + + + + The value for a size criterion is expressed in integer quantities of bytes, + kilobytes (use k or kb after the number), megabytes (m or mb), or gigabytes + (g or gb). + + + + The value for a name is a pattern to match against the filename, potentially + including wildcards. The pattern follows CMD.exe glob rules: * implies one + or more of any character, while ? implies one character. If the name + pattern contains any slashes, it is matched to the entire filename, + including the path; otherwise, it is matched against only the filename + without the path. This means a pattern of "*\*.*" matches all files one + directory level deep, while a pattern of "*.*" matches all files in all + directories. + + + + To specify a name pattern that includes spaces, use single quotes around the + pattern. A pattern of "'* *.*'" will match all files that have spaces in + the filename. The full criteria string for that would be "name = '* *.*'" . + + + + The value for a type criterion is either F (implying a file) or D (implying + a directory). + + + + Some examples: + + + + + criteria + Files retrieved + + + + name != *.xls + any file with an extension that is not .xls + + + + + name = *.mp3 + any file with a .mp3 extension. + + + + + *.mp3 + (same as above) any file with a .mp3 extension. + + + + + attributes = A + all files whose attributes include the Archive bit. + + + + + attributes != H + all files whose attributes do not include the Hidden bit. + + + + + mtime > 2009-01-01 + all files with a last modified time after January 1st, 2009. + + + + + size > 2gb + all files whose uncompressed size is greater than 2gb. + + + + + type = D + all directories in the filesystem. + + + + + + You can combine criteria with the conjunctions AND or OR. Using a string + like "name = *.txt AND size >= 100k" for the selectionCriteria retrieves + entries whose names end in .txt, and whose uncompressed size is greater than + or equal to 100 kilobytes. + + + + For more complex combinations of criteria, you can use parenthesis to group + clauses in the boolean logic. Without parenthesis, the precedence of the + criterion atoms is determined by order of appearance. Unlike the C# + language, the AND conjunction does not take precendence over the logical OR. + This is important only in strings that contain 3 or more criterion atoms. + In other words, "name = *.txt and size > 1000 or attributes = H" implies + "((name = *.txt AND size > 1000) OR attributes = H)" while "attributes = + H OR name = *.txt and size > 1000" evaluates to "((attributes = H OR name + = *.txt) AND size > 1000)". When in doubt, use parenthesis. + + + + Using time properties requires some extra care. If you want to retrieve all + entries that were last updated on 2009 February 14, specify a time range + like so:"mtime >= 2009-02-14 AND mtime < 2009-02-15". Read this to + say: all files updated after 12:00am on February 14th, until 12:00am on + February 15th. You can use the same bracketing approach to specify any time + period - a year, a month, a week, and so on. + + + + The syntax allows one special case: if you provide a string with no spaces, it is + treated as a pattern to match for the filename. Therefore a string like "*.xls" + will be equivalent to specifying "name = *.xls". + + + + There is no logic in this method that insures that the file inclusion + criteria are internally consistent. For example, it's possible to specify + criteria that says the file must have a size of less than 100 bytes, as well + as a size that is greater than 1000 bytes. Obviously no file will ever + satisfy such criteria, but this method does not detect such logical + inconsistencies. The caller is responsible for insuring the criteria are + sensible. + + + + Using this method, the file selection does not recurse into + subdirectories, and the full path of the selected files is included in the + entries added into the zip archive. If you don't like these behaviors, + see the other overloads of this method. + + + + + This example zips up all *.csv files in the current working directory. + + using (ZipFile zip = new ZipFile()) + { + // To just match on filename wildcards, + // use the shorthand form of the selectionCriteria string. + zip.AddSelectedFiles("*.csv"); + zip.Save(PathToZipArchive); + } + + + Using zip As ZipFile = New ZipFile() + zip.AddSelectedFiles("*.csv") + zip.Save(PathToZipArchive) + End Using + + + + The criteria for file selection + + + + Adds to the ZipFile a set of files from the disk that conform to the + specified criteria, optionally recursing into subdirectories. + + + + + This method selects files from the the current working directory matching + the specified criteria, and adds them to the ZipFile. If + recurseDirectories is true, files are also selected from + subdirectories, and the directory structure in the filesystem is + reproduced in the zip archive, rooted at the current working directory. + + + + Using this method, the full path of the selected files is included in the + entries added into the zip archive. If you don't want this behavior, use + one of the overloads of this method that allows the specification of a + directoryInArchive. + + + + For details on the syntax for the selectionCriteria parameter, see . + + + + + + + This example zips up all *.xml files in the current working directory, or any + subdirectory, that are larger than 1mb. + + + using (ZipFile zip = new ZipFile()) + { + // Use a compound expression in the selectionCriteria string. + zip.AddSelectedFiles("name = *.xml and size > 1024kb", true); + zip.Save(PathToZipArchive); + } + + + Using zip As ZipFile = New ZipFile() + ' Use a compound expression in the selectionCriteria string. + zip.AddSelectedFiles("name = *.xml and size > 1024kb", true) + zip.Save(PathToZipArchive) + End Using + + + + The criteria for file selection + + + If true, the file selection will recurse into subdirectories. + + + + + Adds to the ZipFile a set of files from a specified directory in the + filesystem, that conform to the specified criteria. + + + + + This method selects files that conform to the specified criteria, from the + the specified directory on disk, and adds them to the ZipFile. The search + does not recurse into subdirectores. + + + + Using this method, the full filesystem path of the files on disk is + reproduced on the entries added to the zip file. If you don't want this + behavior, use one of the other overloads of this method. + + + + For details on the syntax for the selectionCriteria parameter, see . + + + + + + + This example zips up all *.xml files larger than 1mb in the directory + given by "d:\rawdata". + + + using (ZipFile zip = new ZipFile()) + { + // Use a compound expression in the selectionCriteria string. + zip.AddSelectedFiles("name = *.xml and size > 1024kb", "d:\\rawdata"); + zip.Save(PathToZipArchive); + } + + + + Using zip As ZipFile = New ZipFile() + ' Use a compound expression in the selectionCriteria string. + zip.AddSelectedFiles("name = *.xml and size > 1024kb", "d:\rawdata) + zip.Save(PathToZipArchive) + End Using + + + + The criteria for file selection + + + The name of the directory on the disk from which to select files. + + + + + Adds to the ZipFile a set of files from the specified directory on disk, + that conform to the specified criteria. + + + + + + This method selects files from the the specified disk directory matching + the specified selection criteria, and adds them to the ZipFile. If + recurseDirectories is true, files are also selected from + subdirectories. + + + + The full directory structure in the filesystem is reproduced on the + entries added to the zip archive. If you don't want this behavior, use + one of the overloads of this method that allows the specification of a + directoryInArchive. + + + + For details on the syntax for the selectionCriteria parameter, see . + + + + + + This example zips up all *.csv files in the "files" directory, or any + subdirectory, that have been saved since 2009 February 14th. + + + using (ZipFile zip = new ZipFile()) + { + // Use a compound expression in the selectionCriteria string. + zip.AddSelectedFiles("name = *.csv and mtime > 2009-02-14", "files", true); + zip.Save(PathToZipArchive); + } + + + Using zip As ZipFile = New ZipFile() + ' Use a compound expression in the selectionCriteria string. + zip.AddSelectedFiles("name = *.csv and mtime > 2009-02-14", "files", true) + zip.Save(PathToZipArchive) + End Using + + + + + This example zips up all files in the current working + directory, and all its child directories, except those in + the excludethis subdirectory. + + Using Zip As ZipFile = New ZipFile(zipfile) + Zip.AddSelectedFfiles("name != 'excludethis\*.*'", datapath, True) + Zip.Save() + End Using + + + + The criteria for file selection + + + The filesystem path from which to select files. + + + + If true, the file selection will recurse into subdirectories. + + + + + Adds to the ZipFile a selection of files from the specified directory on + disk, that conform to the specified criteria, and using a specified root + path for entries added to the zip archive. + + + + + This method selects files from the specified disk directory matching the + specified selection criteria, and adds those files to the ZipFile, using + the specified directory path in the archive. The search does not recurse + into subdirectories. For details on the syntax for the selectionCriteria + parameter, see . + + + + + + + This example zips up all *.psd files in the "photos" directory that have + been saved since 2009 February 14th, and puts them all in a zip file, + using the directory name of "content" in the zip archive itself. When the + zip archive is unzipped, the folder containing the .psd files will be + named "content". + + + using (ZipFile zip = new ZipFile()) + { + // Use a compound expression in the selectionCriteria string. + zip.AddSelectedFiles("name = *.psd and mtime > 2009-02-14", "photos", "content"); + zip.Save(PathToZipArchive); + } + + + Using zip As ZipFile = New ZipFile + zip.AddSelectedFiles("name = *.psd and mtime > 2009-02-14", "photos", "content") + zip.Save(PathToZipArchive) + End Using + + + + + The criteria for selection of files to add to the ZipFile. + + + + The path to the directory in the filesystem from which to select files. + + + + Specifies a directory path to use to in place of the + directoryOnDisk. This path may, or may not, correspond to a real + directory in the current filesystem. If the files within the zip are + later extracted, this is the path used for the extracted file. Passing + null (nothing in VB) will use the path on the file name, if any; in other + words it would use directoryOnDisk, plus any subdirectory. Passing + the empty string ("") will insert the item at the root path within the + archive. + + + + + Adds to the ZipFile a selection of files from the specified directory on + disk, that conform to the specified criteria, optionally recursing through + subdirectories, and using a specified root path for entries added to the + zip archive. + + + + This method selects files from the specified disk directory that match the + specified selection criteria, and adds those files to the ZipFile, using + the specified directory path in the archive. If recurseDirectories + is true, files are also selected from subdirectories, and the directory + structure in the filesystem is reproduced in the zip archive, rooted at + the directory specified by directoryOnDisk. For details on the + syntax for the selectionCriteria parameter, see . + + + + + This example zips up all files that are NOT *.pst files, in the current + working directory and any subdirectories. + + + using (ZipFile zip = new ZipFile()) + { + zip.AddSelectedFiles("name != *.pst", SourceDirectory, "backup", true); + zip.Save(PathToZipArchive); + } + + + Using zip As ZipFile = New ZipFile + zip.AddSelectedFiles("name != *.pst", SourceDirectory, "backup", true) + zip.Save(PathToZipArchive) + End Using + + + + + The criteria for selection of files to add to the ZipFile. + + + + The path to the directory in the filesystem from which to select files. + + + + Specifies a directory path to use to in place of the + directoryOnDisk. This path may, or may not, correspond to a real + directory in the current filesystem. If the files within the zip are + later extracted, this is the path used for the extracted file. Passing + null (nothing in VB) will use the path on the file name, if any; in other + words it would use directoryOnDisk, plus any subdirectory. Passing + the empty string ("") will insert the item at the root path within the + archive. + + + + If true, the method also scans subdirectories for files matching the + criteria. + + + + + Updates the ZipFile with a selection of files from the disk that conform + to the specified criteria. + + + + This method selects files from the specified disk directory that match the + specified selection criteria, and Updates the ZipFile with those + files, using the specified directory path in the archive. If + recurseDirectories is true, files are also selected from + subdirectories, and the directory structure in the filesystem is + reproduced in the zip archive, rooted at the directory specified by + directoryOnDisk. For details on the syntax for the + selectionCriteria parameter, see . + + + + The criteria for selection of files to add to the ZipFile. + + + + The path to the directory in the filesystem from which to select files. + + + + Specifies a directory path to use to in place of the + directoryOnDisk. This path may, or may not, correspond to a + real directory in the current filesystem. If the files within the zip + are later extracted, this is the path used for the extracted file. + Passing null (nothing in VB) will use the path on the file name, if + any; in other words it would use directoryOnDisk, plus any + subdirectory. Passing the empty string ("") will insert the item at + the root path within the archive. + + + + If true, the method also scans subdirectories for files matching the criteria. + + + + + + + Retrieve entries from the zipfile by specified criteria. + + + + + This method allows callers to retrieve the collection of entries from the zipfile + that fit the specified criteria. The criteria are described in a string format, and + can include patterns for the filename; constraints on the size of the entry; + constraints on the last modified, created, or last accessed time for the file + described by the entry; or the attributes of the entry. + + + + For details on the syntax for the selectionCriteria parameter, see . + + + + This method is intended for use with a ZipFile that has been read from storage. + When creating a new ZipFile, this method will work only after the ZipArchive has + been Saved to the disk (the ZipFile class subsequently and implicitly reads the Zip + archive from storage.) Calling SelectEntries on a ZipFile that has not yet been + saved will deliver undefined results. + + + + + Thrown if selectionCriteria has an invalid syntax. + + + + This example selects all the PhotoShop files from within an archive, and extracts them + to the current working directory. + + using (ZipFile zip1 = ZipFile.Read(ZipFileName)) + { + var PhotoShopFiles = zip1.SelectEntries("*.psd"); + foreach (ZipEntry psd in PhotoShopFiles) + { + psd.Extract(); + } + } + + + Using zip1 As ZipFile = ZipFile.Read(ZipFileName) + Dim PhotoShopFiles as ICollection(Of ZipEntry) + PhotoShopFiles = zip1.SelectEntries("*.psd") + Dim psd As ZipEntry + For Each psd In PhotoShopFiles + psd.Extract + Next + End Using + + + the string that specifies which entries to select + a collection of ZipEntry objects that conform to the inclusion spec + + + + Retrieve entries from the zipfile by specified criteria. + + + + + This method allows callers to retrieve the collection of entries from the zipfile + that fit the specified criteria. The criteria are described in a string format, and + can include patterns for the filename; constraints on the size of the entry; + constraints on the last modified, created, or last accessed time for the file + described by the entry; or the attributes of the entry. + + + + For details on the syntax for the selectionCriteria parameter, see . + + + + This method is intended for use with a ZipFile that has been read from storage. + When creating a new ZipFile, this method will work only after the ZipArchive has + been Saved to the disk (the ZipFile class subsequently and implicitly reads the Zip + archive from storage.) Calling SelectEntries on a ZipFile that has not yet been + saved will deliver undefined results. + + + + + Thrown if selectionCriteria has an invalid syntax. + + + + + using (ZipFile zip1 = ZipFile.Read(ZipFileName)) + { + var UpdatedPhotoShopFiles = zip1.SelectEntries("*.psd", "UpdatedFiles"); + foreach (ZipEntry e in UpdatedPhotoShopFiles) + { + // prompt for extract here + if (WantExtract(e.FileName)) + e.Extract(); + } + } + + + Using zip1 As ZipFile = ZipFile.Read(ZipFileName) + Dim UpdatedPhotoShopFiles As ICollection(Of ZipEntry) = zip1.SelectEntries("*.psd", "UpdatedFiles") + Dim e As ZipEntry + For Each e In UpdatedPhotoShopFiles + ' prompt for extract here + If Me.WantExtract(e.FileName) Then + e.Extract + End If + Next + End Using + + + the string that specifies which entries to select + + + the directory in the archive from which to select entries. If null, then + all directories in the archive are used. + + + a collection of ZipEntry objects that conform to the inclusion spec + + + + Remove entries from the zipfile by specified criteria. + + + + + This method allows callers to remove the collection of entries from the zipfile + that fit the specified criteria. The criteria are described in a string format, and + can include patterns for the filename; constraints on the size of the entry; + constraints on the last modified, created, or last accessed time for the file + described by the entry; or the attributes of the entry. + + + + For details on the syntax for the selectionCriteria parameter, see . + + + + This method is intended for use with a ZipFile that has been read from storage. + When creating a new ZipFile, this method will work only after the ZipArchive has + been Saved to the disk (the ZipFile class subsequently and implicitly reads the Zip + archive from storage.) Calling SelectEntries on a ZipFile that has not yet been + saved will deliver undefined results. + + + + + Thrown if selectionCriteria has an invalid syntax. + + + + This example removes all entries in a zip file that were modified prior to January 1st, 2008. + + using (ZipFile zip1 = ZipFile.Read(ZipFileName)) + { + // remove all entries from prior to Jan 1, 2008 + zip1.RemoveEntries("mtime < 2008-01-01"); + // don't forget to save the archive! + zip1.Save(); + } + + + Using zip As ZipFile = ZipFile.Read(ZipFileName) + ' remove all entries from prior to Jan 1, 2008 + zip1.RemoveEntries("mtime < 2008-01-01") + ' do not forget to save the archive! + zip1.Save + End Using + + + the string that specifies which entries to select + the number of entries removed + + + + Remove entries from the zipfile by specified criteria, and within the specified + path in the archive. + + + + + This method allows callers to remove the collection of entries from the zipfile + that fit the specified criteria. The criteria are described in a string format, and + can include patterns for the filename; constraints on the size of the entry; + constraints on the last modified, created, or last accessed time for the file + described by the entry; or the attributes of the entry. + + + + For details on the syntax for the selectionCriteria parameter, see . + + + + This method is intended for use with a ZipFile that has been read from storage. + When creating a new ZipFile, this method will work only after the ZipArchive has + been Saved to the disk (the ZipFile class subsequently and implicitly reads the Zip + archive from storage.) Calling SelectEntries on a ZipFile that has not yet been + saved will deliver undefined results. + + + + + Thrown if selectionCriteria has an invalid syntax. + + + + + using (ZipFile zip1 = ZipFile.Read(ZipFileName)) + { + // remove all entries from prior to Jan 1, 2008 + zip1.RemoveEntries("mtime < 2008-01-01", "documents"); + // a call to ZipFile.Save will make the modifications permanent + zip1.Save(); + } + + + Using zip As ZipFile = ZipFile.Read(ZipFileName) + ' remove all entries from prior to Jan 1, 2008 + zip1.RemoveEntries("mtime < 2008-01-01", "documents") + ' a call to ZipFile.Save will make the modifications permanent + zip1.Save + End Using + + + + the string that specifies which entries to select + + the directory in the archive from which to select entries. If null, then + all directories in the archive are used. + + the number of entries removed + + + + Selects and Extracts a set of Entries from the ZipFile. + + + + + The entries are extracted into the current working directory. + + + + If any of the files to be extracted already exist, then the action taken is as + specified in the property on the + corresponding ZipEntry instance. By default, the action taken in this case is to + throw an exception. + + + + For information on the syntax of the selectionCriteria string, + see . + + + + + This example shows how extract all XML files modified after 15 January 2009. + + using (ZipFile zip = ZipFile.Read(zipArchiveName)) + { + zip.ExtractSelectedEntries("name = *.xml and mtime > 2009-01-15"); + } + + + the selection criteria for entries to extract. + + + + + + Selects and Extracts a set of Entries from the ZipFile. + + + + + The entries are extracted into the current working directory. When extraction would would + overwrite an existing filesystem file, the action taken is as specified in the + parameter. + + + + For information on the syntax of the string describing the entry selection criteria, + see . + + + + + This example shows how extract all XML files modified after 15 January 2009, + overwriting any existing files. + + using (ZipFile zip = ZipFile.Read(zipArchiveName)) + { + zip.ExtractSelectedEntries("name = *.xml and mtime > 2009-01-15", + ExtractExistingFileAction.OverwriteSilently); + } + + + + the selection criteria for entries to extract. + + + The action to take if extraction would overwrite an existing file. + + + + + Selects and Extracts a set of Entries from the ZipFile. + + + + + The entries are selected from the specified directory within the archive, and then + extracted into the current working directory. + + + + If any of the files to be extracted already exist, then the action taken is as + specified in the property on the + corresponding ZipEntry instance. By default, the action taken in this case is to + throw an exception. + + + + For information on the syntax of the string describing the entry selection criteria, + see . + + + + + This example shows how extract all XML files modified after 15 January 2009, + and writes them to the "unpack" directory. + + using (ZipFile zip = ZipFile.Read(zipArchiveName)) + { + zip.ExtractSelectedEntries("name = *.xml and mtime > 2009-01-15","unpack"); + } + + + + the selection criteria for entries to extract. + + + the directory in the archive from which to select entries. If null, then + all directories in the archive are used. + + + + + + + Selects and Extracts a set of Entries from the ZipFile. + + + + + The entries are extracted into the specified directory. If any of the files to be + extracted already exist, an exception will be thrown. + + + For information on the syntax of the string describing the entry selection criteria, + see . + + + + the selection criteria for entries to extract. + + + the directory in the archive from which to select entries. If null, then + all directories in the archive are used. + + + + the directory on the disk into which to extract. It will be created + if it does not exist. + + + + + Selects and Extracts a set of Entries from the ZipFile. + + + + + The entries are extracted into the specified directory. When extraction would would + overwrite an existing filesystem file, the action taken is as specified in the + parameter. + + + + For information on the syntax of the string describing the entry selection criteria, + see . + + + + + This example shows how extract all files with an XML extension or with a size larger than 100,000 bytes, + and puts them in the unpack directory. For any files that already exist in + that destination directory, they will not be overwritten. + + using (ZipFile zip = ZipFile.Read(zipArchiveName)) + { + zip.ExtractSelectedEntries("name = *.xml or size > 100000", + null, + "unpack", + ExtractExistingFileAction.DontOverwrite); + } + + + + the selection criteria for entries to extract. + + + The directory on the disk into which to extract. It will be created if it does not exist. + + + + The directory in the archive from which to select entries. If null, then + all directories in the archive are used. + + + + The action to take if extraction would overwrite an existing file. + + + + + + + + Static constructor for ZipFile + + + Code Pages 437 and 1252 for English are same + Code Page 1252 Windows Latin 1 (ANSI) - + Code Page 437 MS-DOS Latin US - + + + + + The default text encoding used in zip archives. It is numeric 437, also + known as IBM437. + + + + + + Generic IEnumerator support, for use of a ZipFile in an enumeration. + + + + You probably do not want to call GetEnumerator explicitly. Instead + it is implicitly called when you use a loop in C#, or a + For Each loop in VB.NET. + + + + This example reads a zipfile of a given name, then enumerates the + entries in that zip file, and displays the information about each + entry on the Console. + + using (ZipFile zip = ZipFile.Read(zipfile)) + { + bool header = true; + foreach (ZipEntry e in zip) + { + if (header) + { + System.Console.WriteLine("Zipfile: {0}", zip.Name); + System.Console.WriteLine("Version Needed: 0x{0:X2}", e.VersionNeeded); + System.Console.WriteLine("BitField: 0x{0:X2}", e.BitField); + System.Console.WriteLine("Compression Method: 0x{0:X2}", e.CompressionMethod); + System.Console.WriteLine("\n{1,-22} {2,-6} {3,4} {4,-8} {0}", + "Filename", "Modified", "Size", "Ratio", "Packed"); + System.Console.WriteLine(new System.String('-', 72)); + header = false; + } + + System.Console.WriteLine("{1,-22} {2,-6} {3,4:F0}% {4,-8} {0}", + e.FileName, + e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"), + e.UncompressedSize, + e.CompressionRatio, + e.CompressedSize); + + e.Extract(); + } + } + + + + Dim ZipFileToExtract As String = "c:\foo.zip" + Using zip As ZipFile = ZipFile.Read(ZipFileToExtract) + Dim header As Boolean = True + Dim e As ZipEntry + For Each e In zip + If header Then + Console.WriteLine("Zipfile: {0}", zip.Name) + Console.WriteLine("Version Needed: 0x{0:X2}", e.VersionNeeded) + Console.WriteLine("BitField: 0x{0:X2}", e.BitField) + Console.WriteLine("Compression Method: 0x{0:X2}", e.CompressionMethod) + Console.WriteLine(ChrW(10) & "{1,-22} {2,-6} {3,4} {4,-8} {0}", _ + "Filename", "Modified", "Size", "Ratio", "Packed" ) + Console.WriteLine(New String("-"c, 72)) + header = False + End If + Console.WriteLine("{1,-22} {2,-6} {3,4:F0}% {4,-8} {0}", _ + e.FileName, _ + e.LastModified.ToString("yyyy-MM-dd HH:mm:ss"), _ + e.UncompressedSize, _ + e.CompressionRatio, _ + e.CompressedSize ) + e.Extract + Next + End Using + + + + A generic enumerator suitable for use within a foreach loop. + + + + An IEnumerator, for use of a ZipFile in a foreach construct. + + + + This method is included for COM support. An application generally does not call + this method directly. It is called implicitly by COM clients when enumerating + the entries in the ZipFile instance. In VBScript, this is done with a For Each + statement. In Javascript, this is done with new Enumerator(zipfile). + + + + The IEnumerator over the entries in the ZipFile. + + + + + Options for using ZIP64 extensions when saving zip archives. + + + + + + Designed many years ago, the original zip + specification from PKWARE allowed for 32-bit quantities for the + compressed and uncompressed sizes of zip entries, as well as a 32-bit quantity + for specifying the length of the zip archive itself, and a maximum of 65535 + entries. These limits are now regularly exceeded in many backup and archival + scenarios. Recently, PKWare added extensions to the original zip spec, called + "ZIP64 extensions", to raise those limitations. This property governs whether + DotNetZip will use those extensions when writing zip archives. The use of + these extensions is optional and explicit in DotNetZip because, despite the + status of ZIP64 as a bona fide standard, many other zip tools and libraries do + not support ZIP64, and therefore a zip file with ZIP64 extensions may be + unreadable by some of those other tools. + + + + Set this property to to always use ZIP64 + extensions when saving, regardless of whether your zip archive needs it. + Suppose you add 5 files, each under 100k, to a ZipFile. If you specify Always + for this flag, you will get a ZIP64 archive, though the archive does not need + to use ZIP64 because none of the original zip limits had been exceeded. + + + + Set this property to to tell the DotNetZip + library to never use ZIP64 extensions. This is useful for maximum + compatibility and interoperability, at the expense of the capability of + handling large files or large archives. NB: Windows Explorer in Windows XP + and Windows Vista cannot currently extract files from a zip64 archive, so if + you want to guarantee that a zip archive produced by this library will work in + Windows Explorer, use Never. If you set this property to , and your application creates a zip that would + exceed one of the Zip limits, the library will throw an exception while saving + the zip file. + + + + Set this property to to tell the + DotNetZip library to use the ZIP64 extensions when required by the + entry. After the file is compressed, the original and compressed sizes are + checked, and if they exceed the limits described above, then zip64 can be + used. That is the general idea, but there is an additional wrinkle when saving + to a non-seekable device, like the ASP.NET Response.OutputStream, or + Console.Out. When using non-seekable streams for output, the entry + header - which indicates whether zip64 is in use - is emitted before it is + known if zip64 is necessary. It is only after all entries have been saved + that it can be known if ZIP64 will be required. On seekable output streams, + after saving all entries, the library can seek backward and re-emit the zip + file header to be consistent with the actual ZIP64 requirement. But using a + non-seekable output stream, the library cannot seek backward, so the header + can never be changed. In other words, the archive's use of ZIP64 extensions is + not alterable after the header is emitted. Therefore, when saving to + non-seekable streams, using is the same + as using : it will always produce a zip + archive that uses ZIP64 extensions. + + + + + + + The default behavior, which is "Never". + (For COM clients, this is a 0 (zero).) + + + + + Do not use ZIP64 extensions when writing zip archives. + (For COM clients, this is a 0 (zero).) + + + + + Use ZIP64 extensions when writing zip archives, as necessary. + For example, when a single entry exceeds 0xFFFFFFFF in size, or when the archive as a whole + exceeds 0xFFFFFFFF in size, or when there are more than 65535 entries in an archive. + (For COM clients, this is a 1.) + + + + + Always use ZIP64 extensions when writing zip archives, even when unnecessary. + (For COM clients, this is a 2.) + + + + + An enum representing the values on a three-way toggle switch + for various options in the library. This might be used to + specify whether to employ a particular text encoding, or to use + ZIP64 extensions, or some other option. + + + + + The default behavior. This is the same as "Never". + (For COM clients, this is a 0 (zero).) + + + + + Never use the associated option. + (For COM clients, this is a 0 (zero).) + + + + + Use the associated behavior "as necessary." + (For COM clients, this is a 1.) + + + + + Use the associated behavior Always, whether necessary or not. + (For COM clients, this is a 2.) + + + + + A class for collecting the various options that can be used when + Reading zip files for extraction or update. + + + + + When reading a zip file, there are several options an + application can set, to modify how the file is read, or what + the library does while reading. This class collects those + options into one container. + + + + Pass an instance of the ReadOptions class into the + ZipFile.Read() method. + + + . + . + + + + + An event handler for Read operations. When opening large zip + archives, you may want to display a progress bar or other + indicator of status progress while reading. This parameter + allows you to specify a ReadProgress Event Handler directly. + When you call Read(), the progress event is invoked as + necessary. + + + + + The System.IO.TextWriter to use for writing verbose status messages + during operations on the zip archive. A console application may wish to + pass System.Console.Out to get messages on the Console. A graphical + or headless application may wish to capture the messages in a different + TextWriter, such as a System.IO.StringWriter. + + + + + The System.Text.Encoding to use when reading in the zip archive. Be + careful specifying the encoding. If the value you use here is not the same + as the Encoding used when the zip archive was created (possibly by a + different archiver) you will get unexpected results and possibly exceptions. + + + + + + + + Provides a stream metaphor for reading zip files. + + + + + This class provides an alternative programming model for reading zip files to + the one enabled by the class. Use this when reading zip + files, as an alternative to the class, when you would + like to use a Stream class to read the file. + + + + Some application designs require a readable stream for input. This stream can + be used to read a zip file, and extract entries. + + + + Both the ZipInputStream class and the ZipFile class can be used + to read and extract zip files. Both of them support many of the common zip + features, including Unicode, different compression levels, and ZIP64. The + programming models differ. For example, when extracting entries via calls to + the GetNextEntry() and Read() methods on the + ZipInputStream class, the caller is responsible for creating the file, + writing the bytes into the file, setting the attributes on the file, and + setting the created, last modified, and last accessed timestamps on the + file. All of these things are done automatically by a call to ZipEntry.Extract(). For this reason, the + ZipInputStream is generally recommended for when your application wants + to extract the data, without storing that data into a file. + + + + Aside from the obvious differences in programming model, there are some + differences in capability between the ZipFile class and the + ZipInputStream class. + + + + + ZipFile can be used to create or update zip files, or read and + extract zip files. ZipInputStream can be used only to read and + extract zip files. If you want to use a stream to create zip files, check + out the . + + + + ZipInputStream cannot read segmented or spanned + zip files. + + + + ZipInputStream will not read Zip file comments. + + + + When reading larger files, ZipInputStream will always underperform + ZipFile. This is because the ZipInputStream does a full scan on the + zip file, while the ZipFile class reads the central directory of the + zip file. + + + + + + + + + Create a ZipInputStream, wrapping it around an existing stream. + + + + + + While the class is generally easier + to use, this class provides an alternative to those + applications that want to read from a zipfile directly, + using a . + + + + Both the ZipInputStream class and the ZipFile class can be used + to read and extract zip files. Both of them support many of the common zip + features, including Unicode, different compression levels, and ZIP64. The + programming models differ. For example, when extracting entries via calls to + the GetNextEntry() and Read() methods on the + ZipInputStream class, the caller is responsible for creating the file, + writing the bytes into the file, setting the attributes on the file, and + setting the created, last modified, and last accessed timestamps on the + file. All of these things are done automatically by a call to ZipEntry.Extract(). For this reason, the + ZipInputStream is generally recommended for when your application wants + to extract the data, without storing that data into a file. + + + + Aside from the obvious differences in programming model, there are some + differences in capability between the ZipFile class and the + ZipInputStream class. + + + + + ZipFile can be used to create or update zip files, or read and extract + zip files. ZipInputStream can be used only to read and extract zip + files. If you want to use a stream to create zip files, check out the . + + + + ZipInputStream cannot read segmented or spanned + zip files. + + + + ZipInputStream will not read Zip file comments. + + + + When reading larger files, ZipInputStream will always underperform + ZipFile. This is because the ZipInputStream does a full scan on the + zip file, while the ZipFile class reads the central directory of the + zip file. + + + + + + + + The stream to read. It must be readable. This stream will be closed at + the time the ZipInputStream is closed. + + + + + This example shows how to read a zip file, and extract entries, using the + ZipInputStream class. + + + private void Unzip() + { + byte[] buffer= new byte[2048]; + int n; + using (var raw = File.Open(inputFileName, FileMode.Open, FileAccess.Read)) + { + using (var input= new ZipInputStream(raw)) + { + ZipEntry e; + while (( e = input.GetNextEntry()) != null) + { + if (e.IsDirectory) continue; + string outputPath = Path.Combine(extractDir, e.FileName); + using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite)) + { + while ((n= input.Read(buffer, 0, buffer.Length)) > 0) + { + output.Write(buffer,0,n); + } + } + } + } + } + } + + + + Private Sub UnZip() + Dim inputFileName As String = "MyArchive.zip" + Dim extractDir As String = "extract" + Dim buffer As Byte() = New Byte(2048) {} + Using raw As FileStream = File.Open(inputFileName, FileMode.Open, FileAccess.Read) + Using input As ZipInputStream = New ZipInputStream(raw) + Dim e As ZipEntry + Do While (Not e = input.GetNextEntry Is Nothing) + If Not e.IsDirectory Then + Using output As FileStream = File.Open(Path.Combine(extractDir, e.FileName), _ + FileMode.Create, FileAccess.ReadWrite) + Dim n As Integer + Do While (n = input.Read(buffer, 0, buffer.Length) > 0) + output.Write(buffer, 0, n) + Loop + End Using + End If + Loop + End Using + End Using + End Sub + + + + + + Create a ZipInputStream, given the name of an existing zip file. + + + + + + This constructor opens a FileStream for the given zipfile, and + wraps a ZipInputStream around that. See the documentation for the + constructor for full details. + + + + While the class is generally easier + to use, this class provides an alternative to those + applications that want to read from a zipfile directly, + using a . + + + + + + The name of the filesystem file to read. + + + + + This example shows how to read a zip file, and extract entries, using the + ZipInputStream class. + + + private void Unzip() + { + byte[] buffer= new byte[2048]; + int n; + using (var input= new ZipInputStream(inputFileName)) + { + ZipEntry e; + while (( e = input.GetNextEntry()) != null) + { + if (e.IsDirectory) continue; + string outputPath = Path.Combine(extractDir, e.FileName); + using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite)) + { + while ((n= input.Read(buffer, 0, buffer.Length)) > 0) + { + output.Write(buffer,0,n); + } + } + } + } + } + + + + Private Sub UnZip() + Dim inputFileName As String = "MyArchive.zip" + Dim extractDir As String = "extract" + Dim buffer As Byte() = New Byte(2048) {} + Using input As ZipInputStream = New ZipInputStream(inputFileName) + Dim e As ZipEntry + Do While (Not e = input.GetNextEntry Is Nothing) + If Not e.IsDirectory Then + Using output As FileStream = File.Open(Path.Combine(extractDir, e.FileName), _ + FileMode.Create, FileAccess.ReadWrite) + Dim n As Integer + Do While (n = input.Read(buffer, 0, buffer.Length) > 0) + output.Write(buffer, 0, n) + Loop + End Using + End If + Loop + End Using + End Sub + + + + + + Create a ZipInputStream, explicitly specifying whether to + keep the underlying stream open. + + + + See the documentation for the ZipInputStream(Stream) + constructor for a discussion of the class, and an example of how to use the class. + + + + The stream to read from. It must be readable. + + + + true if the application would like the stream + to remain open after the ZipInputStream has been closed. + + + + Provides a string representation of the instance. + + + This can be useful for debugging purposes. + + + a string representation of the instance. + + + + The text encoding to use when reading entries into the zip archive, for + those entries whose filenames or comments cannot be encoded with the + default (IBM437) encoding. + + + + + In its + zip specification, PKWare describes two options for encoding + filenames and comments: using IBM437 or UTF-8. But, some archiving tools + or libraries do not follow the specification, and instead encode + characters using the system default code page. For example, WinRAR when + run on a machine in Shanghai may encode filenames with the Big-5 Chinese + (950) code page. This behavior is contrary to the Zip specification, but + it occurs anyway. + + + + When using DotNetZip to read zip archives that use something other than + UTF-8 or IBM437, set this property to specify the code page to use when + reading encoded filenames and comments for each ZipEntry in the zip + file. + + + + This property is "provisional". When the entry in the zip archive is not + explicitly marked as using UTF-8, then IBM437 is used to decode filenames + and comments. If a loss of data would result from using IBM436 - + specifically when encoding and decoding is not reflexive - the codepage + specified here is used. It is possible, therefore, to have a given entry + with a Comment encoded in IBM437 and a FileName encoded with + the specified "provisional" codepage. + + + + When a zip file uses an arbitrary, non-UTF8 code page for encoding, there + is no standard way for the reader application - whether DotNetZip, WinZip, + WinRar, or something else - to know which codepage has been used for the + entries. Readers of zip files are not able to inspect the zip file and + determine the codepage that was used for the entries contained within it. + It is left to the application or user to determine the necessary codepage + when reading zip files encoded this way. If you use an incorrect codepage + when reading a zipfile, you will get entries with filenames that are + incorrect, and the incorrect filenames may even contain characters that + are not legal for use within filenames in Windows. Extracting entries with + illegal characters in the filenames will lead to exceptions. It's too bad, + but this is just the way things are with code pages in zip files. Caveat + Emptor. + + + + + + + Size of the work buffer to use for the ZLIB codec during decompression. + + + + Setting this affects the performance and memory efficiency of compression + and decompression. For larger files, setting this to a larger size may + improve performance, but the exact numbers vary depending on available + memory, and a bunch of other variables. I don't have good firm + recommendations on how to set it. You'll have to test it yourself. Or + just leave it alone and accept the default. + + + + + Sets the password to be used on the ZipInputStream instance. + + + + + + When reading a zip archive, this password is used to read and decrypt the + entries that are encrypted within the zip file. When entries within a zip + file use different passwords, set the appropriate password for the entry + before the first call to Read() for each entry. + + + + When reading an entry that is not encrypted, the value of this property is + ignored. + + + + + + + This example uses the ZipInputStream to read and extract entries from a + zip file, using a potentially different password for each entry. + + + byte[] buffer= new byte[2048]; + int n; + using (var raw = File.Open(_inputFileName, FileMode.Open, FileAccess.Read )) + { + using (var input= new ZipInputStream(raw)) + { + ZipEntry e; + while (( e = input.GetNextEntry()) != null) + { + input.Password = PasswordForEntry(e.FileName); + if (e.IsDirectory) continue; + string outputPath = Path.Combine(_extractDir, e.FileName); + using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite)) + { + while ((n= input.Read(buffer,0,buffer.Length)) > 0) + { + output.Write(buffer,0,n); + } + } + } + } + } + + + + + + + Read the data from the stream into the buffer. + + + + + The data for the zipentry will be decrypted and uncompressed, as + necessary, before being copied into the buffer. + + + + You must set the property before calling + Read() the first time for an encrypted entry. To determine if an + entry is encrypted and requires a password, check the ZipEntry.Encryption property. + + + + The buffer to hold the data read from the stream. + the offset within the buffer to copy the first byte read. + the number of bytes to read. + the number of bytes read, after decryption and decompression. + + + + Read the next entry from the zip file. + + + + + Call this method just before calling , + to position the pointer in the zip file to the next entry that can be + read. Subsequent calls to Read(), will decrypt and decompress the + data in the zip file, until Read() returns 0. + + + + Each time you call GetNextEntry(), the pointer in the wrapped + stream is moved to the next entry in the zip file. If you call , and thus re-position the pointer within + the file, you will need to call GetNextEntry() again, to insure + that the file pointer is positioned at the beginning of a zip entry. + + + + This method returns the ZipEntry. Using a stream approach, you will + read the raw bytes for an entry in a zip file via calls to Read(). + Alternatively, you can extract an entry into a file, or a stream, by + calling , or one of its siblings. + + + + + + The ZipEntry read. Returns null (or Nothing in VB) if there are no more + entries in the zip file. + + + + + + Dispose the stream. + + + + + This method disposes the ZipInputStream. It may also close the + underlying stream, depending on which constructor was used. + + + + Typically the application will call Dispose() implicitly, via + a using statement in C#, or a Using statement in VB. + + + + Application code won't call this code directly. This method may + be invoked in two distinct scenarios. If disposing == true, the + method has been called directly or indirectly by a user's code, + for example via the public Dispose() method. In this case, both + managed and unmanaged resources can be referenced and disposed. + If disposing == false, the method has been called by the runtime + from inside the object finalizer and this method should not + reference other objects; in that case only unmanaged resources + must be referenced or disposed. + + + + + true if the Dispose method was invoked by user code. + + + + + Always returns true. + + + + + Returns the value of CanSeek for the underlying (wrapped) stream. + + + + + Always returns false. + + + + + Returns the length of the underlying stream. + + + + + Gets or sets the position of the underlying stream. + + + Setting the position is equivalent to calling Seek(value, SeekOrigin.Begin). + + + + + This is a no-op. + + + + + This method always throws a NotSupportedException. + + ignored + ignored + ignored + + + + This method seeks in the underlying stream. + + + + + Call this method if you want to seek around within the zip file for random access. + + + + Applications can intermix calls to Seek() with calls to . After a call to Seek(), + GetNextEntry() will get the next ZipEntry that falls after + the current position in the input stream. You're on your own for finding + out just where to seek in the stream, to get to the various entries. + + + + + the offset point to seek to + the reference point from which to seek + The new position + + + + This method always throws a NotSupportedException. + + ignored + + + + Provides a stream metaphor for generating zip files. + + + + + This class writes zip files, as defined in the specification + for zip files described by PKWare. The compression for this + implementation is provided by a managed-code version of Zlib, included with + DotNetZip in the classes in the Ionic.Zlib namespace. + + + + This class provides an alternative programming model to the one enabled by the + class. Use this when creating zip files, as an + alternative to the class, when you would like to use a + Stream type to write the zip file. + + + + Both the ZipOutputStream class and the ZipFile class can be used + to create zip files. Both of them support many of the common zip features, + including Unicode, different compression levels, and ZIP64. They provide + very similar performance when creating zip files. + + + + The ZipFile class is generally easier to use than + ZipOutputStream and should be considered a higher-level interface. For + example, when creating a zip file via calls to the PutNextEntry() and + Write() methods on the ZipOutputStream class, the caller is + responsible for opening the file, reading the bytes from the file, writing + those bytes into the ZipOutputStream, setting the attributes on the + ZipEntry, and setting the created, last modified, and last accessed + timestamps on the zip entry. All of these things are done automatically by a + call to ZipFile.AddFile(). + For this reason, the ZipOutputStream is generally recommended for use + only when your application emits arbitrary data, not necessarily data from a + filesystem file, directly into a zip file, and does so using a Stream + metaphor. + + + + Aside from the differences in programming model, there are other + differences in capability between the two classes. + + + + + ZipFile can be used to read and extract zip files, in addition to + creating zip files. ZipOutputStream cannot read zip files. If you want + to use a stream to read zip files, check out the class. + + + + ZipOutputStream does not support the creation of segmented or spanned + zip files. + + + + ZipOutputStream cannot produce a self-extracting archive. + + + + + Be aware that the ZipOutputStream class implements the interface. In order for + ZipOutputStream to produce a valid zip file, you use use it within + a using clause (Using in VB), or call the Dispose() method + explicitly. See the examples for how to employ a using clause. + + + + Also, a note regarding compression performance: On the desktop .NET + Framework, DotNetZip can use a multi-threaded compression implementation + that provides significant speed increases on large files, over 300k or so, + at the cost of increased memory use at runtime. (The output of the + compression is almost exactly the same size). But, the multi-threaded + approach incurs a performance hit on smaller files. There's no way for the + ZipOutputStream to know whether parallel compression will be beneficial, + because the ZipOutputStream does not know how much data you will write + through the stream. You may wish to set the property to zero, if you are compressing + large files through ZipOutputStream. This will cause parallel + compression to be used, always. + + + + + + Create a ZipOutputStream, wrapping an existing stream. + + + + + The class is generally easier to use when creating + zip files. The ZipOutputStream offers a different metaphor for creating a + zip file, based on the class. + + + + + + The stream to wrap. It must be writable. This stream will be closed at + the time the ZipOutputStream is closed. + + + + + This example shows how to create a zip file, using the + ZipOutputStream class. + + + private void Zipup() + { + if (filesToZip.Count == 0) + { + System.Console.WriteLine("Nothing to do."); + return; + } + + using (var raw = File.Open(_outputFileName, FileMode.Create, FileAccess.ReadWrite )) + { + using (var output= new ZipOutputStream(raw)) + { + output.Password = "VerySecret!"; + output.Encryption = EncryptionAlgorithm.WinZipAes256; + + foreach (string inputFileName in filesToZip) + { + System.Console.WriteLine("file: {0}", inputFileName); + + output.PutNextEntry(inputFileName); + using (var input = File.Open(inputFileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Write )) + { + byte[] buffer= new byte[2048]; + int n; + while ((n= input.Read(buffer,0,buffer.Length)) > 0) + { + output.Write(buffer,0,n); + } + } + } + } + } + } + + + + Private Sub Zipup() + Dim outputFileName As String = "XmlData.zip" + Dim filesToZip As String() = Directory.GetFiles(".", "*.xml") + If (filesToZip.Length = 0) Then + Console.WriteLine("Nothing to do.") + Else + Using raw As FileStream = File.Open(outputFileName, FileMode.Create, FileAccess.ReadWrite) + Using output As ZipOutputStream = New ZipOutputStream(raw) + output.Password = "VerySecret!" + output.Encryption = EncryptionAlgorithm.WinZipAes256 + Dim inputFileName As String + For Each inputFileName In filesToZip + Console.WriteLine("file: {0}", inputFileName) + output.PutNextEntry(inputFileName) + Using input As FileStream = File.Open(inputFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) + Dim n As Integer + Dim buffer As Byte() = New Byte(2048) {} + Do While (n = input.Read(buffer, 0, buffer.Length) > 0) + output.Write(buffer, 0, n) + Loop + End Using + Next + End Using + End Using + End If + End Sub + + + + + + Create a ZipOutputStream that writes to a filesystem file. + + + + The class is generally easier to use when creating + zip files. The ZipOutputStream offers a different metaphor for creating a + zip file, based on the class. + + + + The name of the zip file to create. + + + + + This example shows how to create a zip file, using the + ZipOutputStream class. + + + private void Zipup() + { + if (filesToZip.Count == 0) + { + System.Console.WriteLine("Nothing to do."); + return; + } + + using (var output= new ZipOutputStream(outputFileName)) + { + output.Password = "VerySecret!"; + output.Encryption = EncryptionAlgorithm.WinZipAes256; + + foreach (string inputFileName in filesToZip) + { + System.Console.WriteLine("file: {0}", inputFileName); + + output.PutNextEntry(inputFileName); + using (var input = File.Open(inputFileName, FileMode.Open, FileAccess.Read, + FileShare.Read | FileShare.Write )) + { + byte[] buffer= new byte[2048]; + int n; + while ((n= input.Read(buffer,0,buffer.Length)) > 0) + { + output.Write(buffer,0,n); + } + } + } + } + } + + + + Private Sub Zipup() + Dim outputFileName As String = "XmlData.zip" + Dim filesToZip As String() = Directory.GetFiles(".", "*.xml") + If (filesToZip.Length = 0) Then + Console.WriteLine("Nothing to do.") + Else + Using output As ZipOutputStream = New ZipOutputStream(outputFileName) + output.Password = "VerySecret!" + output.Encryption = EncryptionAlgorithm.WinZipAes256 + Dim inputFileName As String + For Each inputFileName In filesToZip + Console.WriteLine("file: {0}", inputFileName) + output.PutNextEntry(inputFileName) + Using input As FileStream = File.Open(inputFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) + Dim n As Integer + Dim buffer As Byte() = New Byte(2048) {} + Do While (n = input.Read(buffer, 0, buffer.Length) > 0) + output.Write(buffer, 0, n) + Loop + End Using + Next + End Using + End If + End Sub + + + + + + Create a ZipOutputStream. + + + + See the documentation for the ZipOutputStream(Stream) + constructor for an example. + + + + The stream to wrap. It must be writable. + + + + true if the application would like the stream + to remain open after the ZipOutputStream has been closed. + + + + Provides a string representation of the instance. + + + This can be useful for debugging purposes. + + + a string representation of the instance. + + + + Sets the password to be used on the ZipOutputStream instance. + + + + + + When writing a zip archive, this password is applied to the entries, not + to the zip archive itself. It applies to any ZipEntry subsequently + written to the ZipOutputStream. + + + + Using a password does not encrypt or protect the "directory" of the + archive - the list of entries contained in the archive. If you set the + Password property, the password actually applies to individual + entries that are added to the archive, subsequent to the setting of this + property. The list of filenames in the archive that is eventually created + will appear in clear text, but the contents of the individual files are + encrypted. This is how Zip encryption works. + + + + If you set this property, and then add a set of entries to the archive via + calls to PutNextEntry, then each entry is encrypted with that + password. You may also want to change the password between adding + different entries. If you set the password, add an entry, then set the + password to null (Nothing in VB), and add another entry, the + first entry is encrypted and the second is not. + + + + When setting the Password, you may also want to explicitly set the property, to specify how to encrypt the entries added + to the ZipFile. If you set the Password to a non-null value and do not + set , then PKZip 2.0 ("Weak") encryption is used. + This encryption is relatively weak but is very interoperable. If + you set the password to a null value (Nothing in VB), + Encryption is reset to None. + + + + Special case: if you wrap a ZipOutputStream around a non-seekable stream, + and use encryption, and emit an entry of zero bytes, the Close() or + PutNextEntry() following the entry will throw an exception. + + + + + + + The Encryption to use for entries added to the ZipOutputStream. + + + + + The specified Encryption is applied to the entries subsequently + written to the ZipOutputStream instance. + + + + If you set this to something other than + EncryptionAlgorithm.None, you will also need to set the + to a non-null, non-empty value in + order to actually get encryption on the entry. + + + + + ZipOutputStream.Password + ZipEntry.Encryption + + + + Size of the work buffer to use for the ZLIB codec during compression. + + + + Setting this may affect performance. For larger files, setting this to a + larger size may improve performance, but I'm not sure. Sorry, I don't + currently have good recommendations on how to set it. You can test it if + you like. + + + + + The compression strategy to use for all entries. + + + + Set the Strategy used by the ZLIB-compatible compressor, when compressing + data for the entries in the zip archive. Different compression strategies + work better on different sorts of data. The strategy parameter can affect + the compression ratio and the speed of compression but not the correctness + of the compresssion. For more information see . + + + + + The type of timestamp attached to the ZipEntry. + + + + Set this in order to specify the kind of timestamp that should be emitted + into the zip file for each entry. + + + + + Sets the compression level to be used for entries subsequently added to + the zip archive. + + + + + Varying the compression level used on entries can affect the + size-vs-speed tradeoff when compression and decompressing data streams + or files. + + + + As with some other properties on the ZipOutputStream class, like , and , + setting this property on a ZipOutputStream + instance will cause the specified CompressionLevel to be used on all + items that are subsequently added to the + ZipOutputStream instance. + + + + If you do not set this property, the default compression level is used, + which normally gives a good balance of compression efficiency and + compression speed. In some tests, using BestCompression can + double the time it takes to compress, while delivering just a small + increase in compression efficiency. This behavior will vary with the + type of data you compress. If you are in doubt, just leave this setting + alone, and accept the default. + + + + + + The compression method used on each entry added to the ZipOutputStream. + + + + + A comment attached to the zip archive. + + + + + + The application sets this property to specify a comment to be embedded + into the generated zip archive. + + + + According to PKWARE's + zip specification, the comment is not encrypted, even if there is a + password set on the zip file. + + + + The specification does not describe how to indicate the encoding used + on a comment string. Many "compliant" zip tools and libraries use + IBM437 as the code page for comments; DotNetZip, too, follows that + practice. On the other hand, there are situations where you want a + Comment to be encoded with something else, for example using code page + 950 "Big-5 Chinese". To fill that need, DotNetZip will encode the + comment following the same procedure it follows for encoding + filenames: (a) if is + Never, it uses the default encoding (IBM437). (b) if is Always, it always uses the + alternate encoding (). (c) if is AsNecessary, it uses the + alternate encoding only if the default encoding is not sufficient for + encoding the comment - in other words if decoding the result does not + produce the original string. This decision is taken at the time of + the call to ZipFile.Save(). + + + + + + + Specify whether to use ZIP64 extensions when saving a zip archive. + + + + + The default value for the property is . is + safest, in the sense that you will not get an Exception if a + pre-ZIP64 limit is exceeded. + + + + You must set this property before calling Write(). + + + + + + + Indicates whether ZIP64 extensions were used when saving the zip archive. + + + + The value is defined only after the ZipOutputStream has been closed. + + + + + Whether the ZipOutputStream should use case-insensitive comparisons when + checking for uniqueness of zip entries. + + + + + Though the zip specification doesn't prohibit zipfiles with duplicate + entries, Sane zip files have no duplicates, and the DotNetZip library + cannot create zip files with duplicate entries. If an application attempts + to call with a name that duplicates one + already used within the archive, the library will throw an Exception. + + + This property allows the application to specify whether the + ZipOutputStream instance considers ordinal case when checking for + uniqueness of zip entries. + + + + + + Indicates whether to encode entry filenames and entry comments using + Unicode (UTF-8). + + + + + The + PKWare zip specification provides for encoding file names and file + comments in either the IBM437 code page, or in UTF-8. This flag selects + the encoding according to that specification. By default, this flag is + false, and filenames and comments are encoded into the zip file in the + IBM437 codepage. Setting this flag to true will specify that filenames + and comments that cannot be encoded with IBM437 will be encoded with + UTF-8. + + + + Zip files created with strict adherence to the PKWare specification with + respect to UTF-8 encoding can contain entries with filenames containing + any combination of Unicode characters, including the full range of + characters from Chinese, Latin, Hebrew, Greek, Cyrillic, and many other + alphabets. However, because at this time, the UTF-8 portion of the PKWare + specification is not broadly supported by other zip libraries and + utilities, such zip files may not be readable by your favorite zip tool or + archiver. In other words, interoperability will decrease if you set this + flag to true. + + + + In particular, Zip files created with strict adherence to the PKWare + specification with respect to UTF-8 encoding will not work well with + Explorer in Windows XP or Windows Vista, because Windows compressed + folders, as far as I know, do not support UTF-8 in zip files. Vista can + read the zip files, but shows the filenames incorrectly. Unpacking from + Windows Vista Explorer will result in filenames that have rubbish + characters in place of the high-order UTF-8 bytes. + + + + Also, zip files that use UTF-8 encoding will not work well with Java + applications that use the java.util.zip classes, as of v5.0 of the Java + runtime. The Java runtime does not correctly implement the PKWare + specification in this regard. + + + + As a result, we have the unfortunate situation that "correct" behavior by + the DotNetZip library with regard to Unicode encoding of filenames during + zip creation will result in zip files that are readable by strictly + compliant and current tools (for example the most recent release of the + commercial WinZip tool); but these zip files will not be readable by + various other tools or libraries, including Windows Explorer. + + + + The DotNetZip library can read and write zip files with UTF8-encoded + entries, according to the PKware spec. If you use DotNetZip for both + creating and reading the zip file, and you use UTF-8, there will be no + loss of information in the filenames. For example, using a self-extractor + created by this library will allow you to unpack files correctly with no + loss of information in the filenames. + + + + If you do not set this flag, it will remain false. If this flag is false, + the ZipOutputStream will encode all filenames and comments using + the IBM437 codepage. This can cause "loss of information" on some + filenames, but the resulting zipfile will be more interoperable with other + utilities. As an example of the loss of information, diacritics can be + lost. The o-tilde character will be down-coded to plain o. The c with a + cedilla (Unicode 0xE7) used in Portugese will be downcoded to a c. + Likewise, the O-stroke character (Unicode 248), used in Danish and + Norwegian, will be down-coded to plain o. Chinese characters cannot be + represented in codepage IBM437; when using the default encoding, Chinese + characters in filenames will be represented as ?. These are all examples + of "information loss". + + + + The loss of information associated to the use of the IBM437 encoding is + inconvenient, and can also lead to runtime errors. For example, using + IBM437, any sequence of 4 Chinese characters will be encoded as ????. If + your application creates a ZipOutputStream, does not set the + encoding, then adds two files, each with names of four Chinese characters + each, this will result in a duplicate filename exception. In the case + where you add a single file with a name containing four Chinese + characters, the zipfile will save properly, but extracting that file + later, with any zip tool, will result in an error, because the question + mark is not legal for use within filenames on Windows. These are just a + few examples of the problems associated to loss of information. + + + + This flag is independent of the encoding of the content within the entries + in the zip file. Think of the zip file as a container - it supports an + encoding. Within the container are other "containers" - the file entries + themselves. The encoding within those entries is independent of the + encoding of the zip archive container for those entries. + + + + Rather than specify the encoding in a binary fashion using this flag, an + application can specify an arbitrary encoding via the property. Setting the encoding + explicitly when creating zip archives will result in non-compliant zip + files that, curiously, are fairly interoperable. The challenge is, the + PKWare specification does not provide for a way to specify that an entry + in a zip archive uses a code page that is neither IBM437 nor UTF-8. + Therefore if you set the encoding explicitly when creating a zip archive, + you must take care upon reading the zip archive to use the same code page. + If you get it wrong, the behavior is undefined and may result in incorrect + filenames, exceptions, stomach upset, hair loss, and acne. + + + + + + + The text encoding to use when emitting entries into the zip archive, for + those entries whose filenames or comments cannot be encoded with the + default (IBM437) encoding. + + + + + In its + zip specification, PKWare describes two options for encoding + filenames and comments: using IBM437 or UTF-8. But, some archiving tools + or libraries do not follow the specification, and instead encode + characters using the system default code page. For example, WinRAR when + run on a machine in Shanghai may encode filenames with the Big-5 Chinese + (950) code page. This behavior is contrary to the Zip specification, but + it occurs anyway. + + + + When using DotNetZip to write zip archives that will be read by one of + these other archivers, set this property to specify the code page to use + when encoding the and for each ZipEntry in the zip file, for + values that cannot be encoded with the default codepage for zip files, + IBM437. This is why this property is "provisional". In all cases, IBM437 + is used where possible, in other words, where no loss of data would + result. It is possible, therefore, to have a given entry with a + Comment encoded in IBM437 and a FileName encoded with the + specified "provisional" codepage. + + + + Be aware that a zip file created after you've explicitly set the + ProvisionalAlternateEncoding property to a value other than + IBM437 may not be compliant to the PKWare specification, and may not be + readable by compliant archivers. On the other hand, many (most?) + archivers are non-compliant and can read zip files created in arbitrary + code pages. The trick is to use or specify the proper codepage when + reading the zip. + + + + When creating a zip archive using this library, it is possible to change + the value of ProvisionalAlternateEncoding between each entry you + add, and between adding entries and the call to Close(). Don't do + this. It will likely result in a zipfile that is not readable. For best + interoperability, either leave ProvisionalAlternateEncoding + alone, or specify it only once, before adding any entries to the + ZipOutputStream instance. There is one exception to this + recommendation, described later. + + + + When using an arbitrary, non-UTF8 code page for encoding, there is no + standard way for the creator application - whether DotNetZip, WinZip, + WinRar, or something else - to formally specify in the zip file which + codepage has been used for the entries. As a result, readers of zip files + are not able to inspect the zip file and determine the codepage that was + used for the entries contained within it. It is left to the application + or user to determine the necessary codepage when reading zip files encoded + this way. If you use an incorrect codepage when reading a zipfile, you + will get entries with filenames that are incorrect, and the incorrect + filenames may even contain characters that are not legal for use within + filenames in Windows. Extracting entries with illegal characters in the + filenames will lead to exceptions. It's too bad, but this is just the way + things are with code pages in zip files. Caveat Emptor. + + + + One possible approach for specifying the code page for a given zip file is + to describe the code page in a human-readable form in the Zip comment. For + example, the comment may read "Entries in this archive are encoded in the + Big5 code page". For maximum interoperability, the zip comment in this + case should be encoded in the default, IBM437 code page. In this case, + the zip comment is encoded using a different page than the filenames. To + do this, Specify ProvisionalAlternateEncoding to your desired + region-specific code page, once before adding any entries, and then set + the property and reset + ProvisionalAlternateEncoding to IBM437 before calling Close(). + + + + + + A Text Encoding to use when encoding the filenames and comments for + all the ZipEntry items, during a ZipFile.Save() operation. + + + + Whether the encoding specified here is used during the save depends + on . + + + + + + A flag that tells if and when this instance should apply + AlternateEncoding to encode the filenames and comments associated to + of ZipEntry objects contained within this instance. + + + + + The default text encoding used in zip archives. It is numeric 437, also + known as IBM437. + + + + + + The size threshold for an entry, above which a parallel deflate is used. + + + + + + DotNetZip will use multiple threads to compress any ZipEntry, when + the CompressionMethod is Deflate, and if the entry is + larger than the given size. Zero means "always use parallel + deflate", while -1 means "never use parallel deflate". + + + + If the entry size cannot be known before compression, as with any entry + added via a ZipOutputStream, then Parallel deflate will never be + performed, unless the value of this property is zero. + + + + A parallel deflate operations will speed up the compression of + large files, on computers with multiple CPUs or multiple CPU + cores. For files above 1mb, on a dual core or dual-cpu (2p) + machine, the time required to compress the file can be 70% of the + single-threaded deflate. For very large files on 4p machines the + compression can be done in 30% of the normal time. The downside + is that parallel deflate consumes extra memory during the deflate, + and the deflation is slightly less effective. + + + + Parallel deflate tends to not be as effective as single-threaded deflate + because the original data stream is split into multiple independent + buffers, each of which is compressed in parallel. But because they are + treated independently, there is no opportunity to share compression + dictionaries, and additional framing bytes must be added to the output + stream. For that reason, a deflated stream may be slightly larger when + compressed using parallel deflate, as compared to a traditional + single-threaded deflate. For files of about 512k, the increase over the + normal deflate is as much as 5% of the total compressed size. For larger + files, the difference can be as small as 0.1%. + + + + Multi-threaded compression does not give as much an advantage when using + Encryption. This is primarily because encryption tends to slow down + the entire pipeline. Also, multi-threaded compression gives less of an + advantage when using lower compression levels, for example . You may have to perform + some tests to determine the best approach for your situation. + + + + The default value for this property is -1, which means parallel + compression will not be performed unless you set it to zero. + + + + + + + The maximum number of buffer pairs to use when performing + parallel compression. + + + + + This property sets an upper limit on the number of memory + buffer pairs to create when performing parallel + compression. The implementation of the parallel + compression stream allocates multiple buffers to + facilitate parallel compression. As each buffer fills up, + the stream uses + ThreadPool.QueueUserWorkItem() to compress those + buffers in a background threadpool thread. After a buffer + is compressed, it is re-ordered and written to the output + stream. + + + + A higher number of buffer pairs enables a higher degree of + parallelism, which tends to increase the speed of compression on + multi-cpu computers. On the other hand, a higher number of buffer + pairs also implies a larger memory consumption, more active worker + threads, and a higher cpu utilization for any compression. This + property enables the application to limit its memory consumption and + CPU utilization behavior depending on requirements. + + + + For each compression "task" that occurs in parallel, there are 2 + buffers allocated: one for input and one for output. This property + sets a limit for the number of pairs. The total amount of storage + space allocated for buffering will then be (N*S*2), where N is the + number of buffer pairs, S is the size of each buffer (). By default, DotNetZip allocates 4 buffer + pairs per CPU core, so if your machine has 4 cores, and you retain + the default buffer size of 128k, then the + ParallelDeflateOutputStream will use 4 * 4 * 2 * 128kb of buffer + memory in total, or 4mb, in blocks of 128kb. If you then set this + property to 8, then the number will be 8 * 2 * 128kb of buffer + memory, or 2mb. + + + + CPU utilization will also go up with additional buffers, because a + larger number of buffer pairs allows a larger number of background + threads to compress in parallel. If you find that parallel + compression is consuming too much memory or CPU, you can adjust this + value downward. + + + + The default value is 16. Different values may deliver better or + worse results, depending on your priorities and the dynamic + performance characteristics of your storage and compute resources. + + + + This property is not the number of buffer pairs to use; it is an + upper limit. An illustration: Suppose you have an application that + uses the default value of this property (which is 16), and it runs + on a machine with 2 CPU cores. In that case, DotNetZip will allocate + 4 buffer pairs per CPU core, for a total of 8 pairs. The upper + limit specified by this property has no effect. + + + + The application can set this value at any time, but it is + effective only if set before calling + ZipOutputStream.Write() for the first time. + + + + + + + + + Returns true if an entry by the given name has already been written + to the ZipOutputStream. + + + + The name of the entry to scan for. + + + + true if an entry by the given name has already been written. + + + + + Write the data from the buffer to the stream. + + + + As the application writes data into this stream, the data may be + compressed and encrypted before being written out to the underlying + stream, depending on the settings of the + and the properties. + + + The buffer holding data to write to the stream. + the offset within that data array to find the first byte to write. + the number of bytes to write. + + + + Specify the name of the next entry that will be written to the zip file. + + + + + Call this method just before calling , to + specify the name of the entry that the next set of bytes written to + the ZipOutputStream belongs to. All subsequent calls to Write, + until the next call to PutNextEntry, + will be inserted into the named entry in the zip file. + + + + If the used in PutNextEntry() ends in + a slash, then the entry added is marked as a directory. Because directory + entries do not contain data, a call to Write(), before an + intervening additional call to PutNextEntry(), will throw an + exception. + + + + If you don't call Write() between two calls to + PutNextEntry(), the first entry is inserted into the zip file as a + file of zero size. This may be what you want. + + + + Because PutNextEntry() closes out the prior entry, if any, this + method may throw if there is a problem with the prior entry. + + + + This method returns the ZipEntry. You can modify public properties + on the ZipEntry, such as , , and so on, until the first call to + ZipOutputStream.Write(), or until the next call to + PutNextEntry(). If you modify the ZipEntry after + having called Write(), you may get a runtime exception, or you may + silently get an invalid zip archive. + + + + + + + This example shows how to create a zip file, using the + ZipOutputStream class. + + + private void Zipup() + { + using (FileStream fs raw = File.Open(_outputFileName, FileMode.Create, FileAccess.ReadWrite )) + { + using (var output= new ZipOutputStream(fs)) + { + output.Password = "VerySecret!"; + output.Encryption = EncryptionAlgorithm.WinZipAes256; + output.PutNextEntry("entry1.txt"); + byte[] buffer= System.Text.Encoding.ASCII.GetBytes("This is the content for entry #1."); + output.Write(buffer,0,buffer.Length); + output.PutNextEntry("entry2.txt"); // this will be zero length + output.PutNextEntry("entry3.txt"); + buffer= System.Text.Encoding.ASCII.GetBytes("This is the content for entry #3."); + output.Write(buffer,0,buffer.Length); + } + } + } + + + + + The name of the entry to be added, including any path to be used + within the zip file. + + + + The ZipEntry created. + + + + + + Dispose the stream + + + + + This method writes the Zip Central directory, then closes the stream. The + application must call Dispose() (or Close) in order to produce a valid zip file. + + + + Typically the application will call Dispose() implicitly, via a using + statement in C#, or a Using statement in VB. + + + + + set this to true, always. + + + + Always returns false. + + + + + Always returns false. + + + + + Always returns true. + + + + + Always returns a NotSupportedException. + + + + + Setting this property always returns a NotSupportedException. Getting it + returns the value of the Position on the underlying stream. + + + + + This is a no-op. + + + + + This method always throws a NotSupportedException. + + ignored + ignored + ignored + nothing + + + + This method always throws a NotSupportedException. + + ignored + ignored + nothing + + + + This method always throws a NotSupportedException. + + ignored + + + + Sort-of like a factory method, ForUpdate is used only when + the application needs to update the zip entry metadata for + a segmented zip file, when the starting segment is earlier + than the ending segment, for a particular entry. + + + + The update is always contiguous, never rolls over. As a + result, this method doesn't need to return a ZSS; it can + simply return a FileStream. That's why it's "sort of" + like a Factory method. + + + Caller must Close/Dispose the stream object returned by + this method. + + + + + + Name of the filesystem file corresponding to the current segment. + + + + The name is not always the name currently being used in the + filesystem. When rwMode is RwMode.Write, the filesystem file has a + temporary name until the stream is closed or until the next segment is + started. + + + + + + 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 + + + + Write to the stream. + + the buffer from which to write + the offset at which to start writing + the number of bytes to write + + + + Enumerates the options for a logical conjunction. This enum is intended for use + internally by the FileSelector class. + + + + + FileSelector encapsulates logic that selects files from a source - a zip file + or the filesystem - based on a set of criteria. This class is used internally + by the DotNetZip library, in particular for the AddSelectedFiles() methods. + This class can also be used independently of the zip capability in DotNetZip. + + + + + + The FileSelector class is used internally by the ZipFile class for selecting + files for inclusion into the ZipFile, when the method, or one of + its overloads, is called. It's also used for the methods. Typically, an + application that creates or manipulates Zip archives will not directly + interact with the FileSelector class. + + + + Some applications may wish to use the FileSelector class directly, to + select files from disk volumes based on a set of criteria, without creating or + querying Zip archives. The file selection criteria include: a pattern to + match the filename; the last modified, created, or last accessed time of the + file; the size of the file; and the attributes of the file. + + + + Consult the documentation for + for more information on specifying the selection criteria. + + + + + + + Constructor that allows the caller to specify file selection criteria. + + + + + This constructor allows the caller to specify a set of criteria for + selection of files. + + + + See for a description of + the syntax of the selectionCriteria string. + + + + By default the FileSelector will traverse NTFS Reparse Points. To + change this, use FileSelector(String, bool). + + + + The criteria for file selection. + + + + Constructor that allows the caller to specify file selection criteria. + + + + + This constructor allows the caller to specify a set of criteria for + selection of files. + + + + See for a description of + the syntax of the selectionCriteria string. + + + + The criteria for file selection. + + whether to traverse NTFS reparse points (junctions). + + + + + The string specifying which files to include when retrieving. + + + + + Specify the criteria in statements of 3 elements: a noun, an operator, + and a value. Consider the string "name != *.doc" . The noun is + "name". The operator is "!=", implying "Not Equal". The value is + "*.doc". That criterion, in English, says "all files with a name that + does not end in the .doc extension." + + + + Supported nouns include "name" (or "filename") for the filename; + "atime", "mtime", and "ctime" for last access time, last modfied time, + and created time of the file, respectively; "attributes" (or "attrs") + for the file attributes; "size" (or "length") for the file length + (uncompressed); and "type" for the type of object, either a file or a + directory. The "attributes", "type", and "name" nouns all support = + and != as operators. The "size", "atime", "mtime", and "ctime" nouns + support = and !=, and >, >=, <, <= as well. The times are + taken to be expressed in local time. + + + + Specify values for the file attributes as a string with one or more of + the characters H,R,S,A,I,L in any order, implying file attributes of + Hidden, ReadOnly, System, Archive, NotContextIndexed, and ReparsePoint + (symbolic link) respectively. + + + + To specify a time, use YYYY-MM-DD-HH:mm:ss or YYYY/MM/DD-HH:mm:ss as + the format. If you omit the HH:mm:ss portion, it is assumed to be + 00:00:00 (midnight). + + + + The value for a size criterion is expressed in integer quantities of + bytes, kilobytes (use k or kb after the number), megabytes (m or mb), + or gigabytes (g or gb). + + + + The value for a name is a pattern to match against the filename, + potentially including wildcards. The pattern follows CMD.exe glob + rules: * implies one or more of any character, while ? implies one + character. If the name pattern contains any slashes, it is matched to + the entire filename, including the path; otherwise, it is matched + against only the filename without the path. This means a pattern of + "*\*.*" matches all files one directory level deep, while a pattern of + "*.*" matches all files in all directories. + + + + To specify a name pattern that includes spaces, use single quotes + around the pattern. A pattern of "'* *.*'" will match all files that + have spaces in the filename. The full criteria string for that would + be "name = '* *.*'" . + + + + The value for a type criterion is either F (implying a file) or D + (implying a directory). + + + + Some examples: + + + + + criteria + Files retrieved + + + + name != *.xls + any file with an extension that is not .xls + + + + + name = *.mp3 + any file with a .mp3 extension. + + + + + *.mp3 + (same as above) any file with a .mp3 extension. + + + + + attributes = A + all files whose attributes include the Archive bit. + + + + + attributes != H + all files whose attributes do not include the Hidden bit. + + + + + mtime > 2009-01-01 + all files with a last modified time after January 1st, 2009. + + + + + ctime > 2009/01/01-03:00:00 + all files with a created time after 3am (local time), + on January 1st, 2009. + + + + + size > 2gb + all files whose uncompressed size is greater than 2gb. + + + + + type = D + all directories in the filesystem. + + + + + + You can combine criteria with the conjunctions AND, OR, and XOR. Using + a string like "name = *.txt AND size >= 100k" for the + selectionCriteria retrieves entries whose names end in .txt, and whose + uncompressed size is greater than or equal to 100 kilobytes. + + + + For more complex combinations of criteria, you can use parenthesis to + group clauses in the boolean logic. Absent parenthesis, the + precedence of the criterion atoms is determined by order of + appearance. Unlike the C# language, the AND conjunction does not take + precendence over the logical OR. This is important only in strings + that contain 3 or more criterion atoms. In other words, "name = *.txt + and size > 1000 or attributes = H" implies "((name = *.txt AND size + > 1000) OR attributes = H)" while "attributes = H OR name = *.txt + and size > 1000" evaluates to "((attributes = H OR name = *.txt) + AND size > 1000)". When in doubt, use parenthesis. + + + + Using time properties requires some extra care. If you want to + retrieve all entries that were last updated on 2009 February 14, + specify "mtime >= 2009-02-14 AND mtime < 2009-02-15". Read this + to say: all files updated after 12:00am on February 14th, until + 12:00am on February 15th. You can use the same bracketing approach to + specify any time period - a year, a month, a week, and so on. + + + + The syntax allows one special case: if you provide a string with no + spaces, it is treated as a pattern to match for the filename. + Therefore a string like "*.xls" will be equivalent to specifying "name + = *.xls". This "shorthand" notation does not work with compound + criteria. + + + + There is no logic in this class that insures that the inclusion + criteria are internally consistent. For example, it's possible to + specify criteria that says the file must have a size of less than 100 + bytes, as well as a size that is greater than 1000 bytes. Obviously + no file will ever satisfy such criteria, but this class does not check + for or detect such inconsistencies. + + + + + + Thrown in the setter if the value has an invalid syntax. + + + + + Indicates whether searches will traverse NTFS reparse points, like Junctions. + + + + + Returns a string representation of the FileSelector object. + + The string representation of the boolean logic statement of the file + selection criteria for this instance. + + + + Returns the names of the files in the specified directory + that fit the selection criteria specified in the FileSelector. + + + + This is equivalent to calling + with recurseDirectories = false. + + + + The name of the directory over which to apply the FileSelector + criteria. + + + + A collection of strings containing fully-qualified pathnames of files + that match the criteria specified in the FileSelector instance. + + + + + Returns the names of the files in the specified directory that fit the + selection criteria specified in the FileSelector, optionally recursing + through subdirectories. + + + + This method applies the file selection criteria contained in the + FileSelector to the files contained in the given directory, and + returns the names of files that conform to the criteria. + + + + The name of the directory over which to apply the FileSelector + criteria. + + + + Whether to recurse through subdirectories when applying the file + selection criteria. + + + + A collection of strings containing fully-qualified pathnames of files + that match the criteria specified in the FileSelector instance. + + + + + Retrieve the ZipEntry items in the ZipFile that conform to the specified criteria. + + + + + This method applies the criteria set in the FileSelector instance (as described in + the ) to the specified ZipFile. Using this + method, for example, you can retrieve all entries from the given ZipFile that + have filenames ending in .txt. + + + + Normally, applications would not call this method directly. This method is used + by the ZipFile class. + + + + Using the appropriate SelectionCriteria, you can retrieve entries based on size, + time, and attributes. See for a + description of the syntax of the SelectionCriteria string. + + + + + The ZipFile from which to retrieve entries. + + a collection of ZipEntry objects that conform to the criteria. + + + + Retrieve the ZipEntry items in the ZipFile that conform to the specified criteria. + + + + + This method applies the criteria set in the FileSelector instance (as described in + the ) to the specified ZipFile. Using this + method, for example, you can retrieve all entries from the given ZipFile that + have filenames ending in .txt. + + + + Normally, applications would not call this method directly. This method is used + by the ZipFile class. + + + + This overload allows the selection of ZipEntry instances from the ZipFile to be restricted + to entries contained within a particular directory in the ZipFile. + + + + Using the appropriate SelectionCriteria, you can retrieve entries based on size, + time, and attributes. See for a + description of the syntax of the SelectionCriteria string. + + + + + The ZipFile from which to retrieve entries. + + + the directory in the archive from which to select entries. If null, then + all directories in the archive are used. + + + a collection of ZipEntry objects that conform to the criteria. + + + + Summary description for EnumUtil. + + + + + Returns the value of the DescriptionAttribute if the specified Enum + value has one. If not, returns the ToString() representation of the + Enum value. + + The Enum to get the description for + + + + + Converts the string representation of the name or numeric value of one + or more enumerated constants to an equivalent enumerated object. + Note: use the DescriptionAttribute on enum values to enable this. + + The System.Type of the enumeration. + + A string containing the name or value to convert. + + + + + + Converts the string representation of the name or numeric value of one + or more enumerated constants to an equivalent enumerated object. A + parameter specified whether the operation is case-sensitive. Note: + use the DescriptionAttribute on enum values to enable this. + + The System.Type of the enumeration. + + A string containing the name or value to convert. + + + Whether the operation is case-sensitive or not. + + +
+