From 0125a7c8057618f08864092b89a47c4c3f233bcf Mon Sep 17 00:00:00 2001 From: Info Offbeat Date: Thu, 4 Feb 2016 12:41:47 +0530 Subject: [PATCH 1/5] Improvement Changes --- HandsetDetectionAPI/HD4.cs | 30 +- HandsetDetectionAPI/HDBase.cs | 26 + HandsetDetectionAPI/HDDevice.cs | 58 +- .../bin/Debug/HandsetDetectionAPI.dll | Bin 206336 -> 0 bytes HandsetDetectionAPI/bin/Debug/Ionic.Zip.dll | Bin 463360 -> 0 bytes HandsetDetectionAPI/bin/Debug/Ionic.Zip.xml | 18168 ---------------- .../bin/Debug/nunit.framework.dll | Bin 151552 -> 0 bytes .../bin/Debug/nunit.framework.xml | 10984 ---------- .../obj/Debug/HandsetDetectionAPI.dll | Bin 206336 -> 0 bytes HandsetDetectionAPIKit4/Benchmark.aspx | 31 + HandsetDetectionAPIKit4/Benchmark.aspx.cs | 101 + .../Benchmark.aspx.designer.cs | 60 + HandsetDetectionAPIKit4/Web.csproj | 9 + HandsetDetectionAPIKit4/benchmarkData.txt | 1066 + .../bin/HandsetDetectionAPI.dll | Bin 206336 -> 0 bytes HandsetDetectionAPIKit4/bin/Ionic.Zip.dll | Bin 463360 -> 0 bytes HandsetDetectionAPIKit4/bin/Ionic.Zip.xml | 18168 ---------------- HandsetDetectionAPIKit4/bin/Web.dll | Bin 9728 -> 0 bytes HandsetDetectionAPIKit4/bin/Web.dll.config | 11 - .../bin/nunit.framework.dll | Bin 151552 -> 0 bytes .../bin/nunit.framework.xml | 10984 ---------- HandsetDetectionAPIKit4/obj/Debug/Web.dll | Bin 9728 -> 0 bytes 22 files changed, 1343 insertions(+), 58353 deletions(-) delete mode 100644 HandsetDetectionAPI/bin/Debug/HandsetDetectionAPI.dll delete mode 100644 HandsetDetectionAPI/bin/Debug/Ionic.Zip.dll delete mode 100644 HandsetDetectionAPI/bin/Debug/Ionic.Zip.xml delete mode 100644 HandsetDetectionAPI/bin/Debug/nunit.framework.dll delete mode 100644 HandsetDetectionAPI/bin/Debug/nunit.framework.xml delete mode 100644 HandsetDetectionAPI/obj/Debug/HandsetDetectionAPI.dll create mode 100644 HandsetDetectionAPIKit4/Benchmark.aspx create mode 100644 HandsetDetectionAPIKit4/Benchmark.aspx.cs create mode 100644 HandsetDetectionAPIKit4/Benchmark.aspx.designer.cs create mode 100644 HandsetDetectionAPIKit4/benchmarkData.txt delete mode 100644 HandsetDetectionAPIKit4/bin/HandsetDetectionAPI.dll delete mode 100644 HandsetDetectionAPIKit4/bin/Ionic.Zip.dll delete mode 100644 HandsetDetectionAPIKit4/bin/Ionic.Zip.xml delete mode 100644 HandsetDetectionAPIKit4/bin/Web.dll delete mode 100644 HandsetDetectionAPIKit4/bin/Web.dll.config delete mode 100644 HandsetDetectionAPIKit4/bin/nunit.framework.dll delete mode 100644 HandsetDetectionAPIKit4/bin/nunit.framework.xml delete mode 100644 HandsetDetectionAPIKit4/obj/Debug/Web.dll diff --git a/HandsetDetectionAPI/HD4.cs b/HandsetDetectionAPI/HD4.cs index 77592383..ced41518 100644 --- a/HandsetDetectionAPI/HD4.cs +++ b/HandsetDetectionAPI/HD4.cs @@ -19,11 +19,23 @@ public bool UseLocal { get { - return config["use_local"]; + return Convert.ToBoolean(config["use_local"]); } set { - config["use_local"] = value; + config["use_local"] = value.ToString(); + } + } + + public bool Geoip + { + get + { + return Convert.ToBoolean(config["geoip"]); + } + set + { + config["geoip"] = value.ToString(); } } @@ -63,7 +75,7 @@ public HD4(HttpRequest request, dynamic configuration = null) this.Request = request; if (configuration != null && configuration is IDictionary) { - foreach (var item in (Dictionary)configuration) + foreach (var item in (Dictionary)configuration) { if (config.ContainsKey(item.Key)) { @@ -88,7 +100,7 @@ public HD4(HttpRequest request, dynamic configuration = null) AddConfigSettingFromFile(ApplicationRootDirectory + configFile); } - this.debug = config["debug"]; + this.debug = Debug; this.Store = HDStore.Instance; this.Store.setPath(config["filesdir"], true); @@ -105,11 +117,11 @@ public HD4(HttpRequest request, dynamic configuration = null) /// private void AddConfigSettingFromFile(string configFile) { - Dictionary hdConfig = new Dictionary(); + Dictionary hdConfig = new Dictionary(); var serializer = new JavaScriptSerializer(); string jsonText = System.IO.File.ReadAllText(configFile); - hdConfig = serializer.Deserialize>(jsonText); + hdConfig = serializer.Deserialize>(jsonText); foreach (var item in hdConfig) { @@ -145,7 +157,7 @@ void setup() AddKey("ipaddress", Request.UserHostAddress); AddKey("request_uri", Request.Url.ToString()); - if (!this.UseLocal && config["geoip"]) + if (!UseLocal && Geoip) { // Ip address only used in cloud mode this.detectRequest["ipaddress"] = this.Request.ServerVariables["REMOTE_ADDR"] != null ? this.Request.ServerVariables["REMOTE_ADDR"] : null; @@ -291,9 +303,9 @@ public bool deviceDetect(Dictionary data = null) string fastKey = ""; // If caching enabled then check cache - if (config["cache_requests"]) + if (Cacherequests) { - var headersKeys = requestBody.Keys.Select(c => c.ToLower()).OrderBy(c => c); + var headersKeys = requestBody.Values.Select(c => c).OrderBy(c => c); var serializer = new JavaScriptSerializer(); fastKey = serializer.Serialize(headersKeys).Replace(" ", ""); var objReply = this.cache.read(fastKey); diff --git a/HandsetDetectionAPI/HDBase.cs b/HandsetDetectionAPI/HDBase.cs index d8227bab..635948cb 100644 --- a/HandsetDetectionAPI/HDBase.cs +++ b/HandsetDetectionAPI/HDBase.cs @@ -559,6 +559,32 @@ public bool UseProxy config["use_proxy"] = value; } } + + + public bool Cacherequests + { + get + { + return Convert.ToBoolean(config["cache_requests"]); + } + set + { + config["cache_requests"] = value.ToString(); + } + } + + public bool Debug + { + get + { + return Convert.ToBoolean(config["debug"]); + } + set + { + config["debug"] = value.ToString(); + } + } + public string Username { get diff --git a/HandsetDetectionAPI/HDDevice.cs b/HandsetDetectionAPI/HDDevice.cs index eed42e35..3710127d 100644 --- a/HandsetDetectionAPI/HDDevice.cs +++ b/HandsetDetectionAPI/HDDevice.cs @@ -254,10 +254,10 @@ public Dictionary findRating(string deviceId, Dictionary= Convert.ToInt32(specs["benchmark_min"]) && (int)props["benchmark"] <= Convert.ToInt32(specs["benchmark_max"])) @@ -270,33 +270,33 @@ public Dictionary findRating(string deviceId, Dictionary 0) - { - if ((int)props["benchmark"] >= Convert.ToInt32(specs["benchmark_max"])) - { - // Above range : Calculate how many steps above range - int objbenchmacrk = props["benchmark"]; - int sobjbenchmacrk = Convert.ToInt32(specs["benchmark_max"]); - Double objResult = Convert.ToDouble(Convert.ToDouble(objbenchmacrk - sobjbenchmacrk) / steps); - - tmp = (int)Math.Round(objResult, MidpointRounding.AwayFromZero); - result["benchmark_span"] = (int)10 - (Math.Min(10, Math.Max(0, tmp))); - } - else if ((int)props["benchmark"] <= Convert.ToInt32(specs["benchmark_min"])) - { - // Below range : Calculate how many steps above range - int objbenchmacrk = props["benchmark"]; - int sobjbenchmacrk = Convert.ToInt32(specs["benchmark_min"]); - - - Double objResult = Convert.ToDouble(Convert.ToDouble(sobjbenchmacrk - objbenchmacrk) / steps); - - tmp = (int)Math.Round(objResult, MidpointRounding.AwayFromZero); - result["benchmark_span"] = (int)10 - (Math.Min(10, Math.Max(0, tmp))); - } - } + //steps = (int)Math.Round(Convert.ToDouble((Convert.ToDouble(specs["benchmark_max"]) - Convert.ToDouble(specs["benchmark_min"])) / 10.0)); + //// Outside range + //if (steps > 0) + //{ + // if ((int)props["benchmark"] >= Convert.ToInt32(specs["benchmark_max"])) + // { + // // Above range : Calculate how many steps above range + // int objbenchmacrk = props["benchmark"]; + // int sobjbenchmacrk = Convert.ToInt32(specs["benchmark_max"]); + // Double objResult = Convert.ToDouble(Convert.ToDouble(objbenchmacrk - sobjbenchmacrk) / steps); + + // tmp = (int)Math.Round(objResult, MidpointRounding.AwayFromZero); + // result["benchmark_span"] = (int)10 - (Math.Min(10, Math.Max(0, tmp))); + // } + // else if ((int)props["benchmark"] <= Convert.ToInt32(specs["benchmark_min"])) + // { + // // Below range : Calculate how many steps above range + // int objbenchmacrk = props["benchmark"]; + // int sobjbenchmacrk = Convert.ToInt32(specs["benchmark_min"]); + + + // Double objResult = Convert.ToDouble(Convert.ToDouble(sobjbenchmacrk - objbenchmacrk) / steps); + + // tmp = (int)Math.Round(objResult, MidpointRounding.AwayFromZero); + // result["benchmark_span"] = (int)10 - (Math.Min(10, Math.Max(0, tmp))); + // } + //} } } } diff --git a/HandsetDetectionAPI/bin/Debug/HandsetDetectionAPI.dll b/HandsetDetectionAPI/bin/Debug/HandsetDetectionAPI.dll deleted file mode 100644 index 3c50fa44679cac700f1dfa51ac919d8e3d96696f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 206336 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 diff --git a/HandsetDetectionAPI/bin/Debug/Ionic.Zip.dll b/HandsetDetectionAPI/bin/Debug/Ionic.Zip.dll deleted file mode 100644 index 85e4820f41a0a727367fb0705c7e35be5a2cbda4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 463360 zcmce934k0&b#`xePxnmE>}p4|J2ShIc2>5vZqFrY*M}ryTQawVJz;XVS$|M$IDJu`bqat{8r zHC6Sh>eZ`Puc}^Ey{bNc`@NQ9S(b}`k3Vi%55nc&R{1^j&mD*!s5~@a{blBJYai@; z%IDTza>K5<@!fHBeSGCj<5ypK^UcvM<5yif9^ZQN_^zABPrvZu@tdM+u5I@B2S*vy z7oA~QPw8{4xbm?}lhVFs*=w_XS<4E1%kmWZ;Sm0D__xBftU>YHN;d(dU;geuJmByC zl8<_AeIb+b|E_C-n%cS%crTC3c7p$#w}}SGoFjD22f~Y-C5Bb+@8O!puQPjdt-!zq}2k=f@^R| zy3=~HiT8EnEB;8EZKbT;PfuB&`1?L9BT&n__h{RiU+-8Kja$|o26iZC^NTJo4eej| z^)J8lITyV2kDvYH@1K0sxmT?C%*&qq+!s9bk56elzWHTqezyOFSB=f2j(X{R@0$7O z$Ukj*_;ts>EcO0xpK{IC$+Lg3_Y>cL@+W?D!pJcb=YRXa9bXza=d2gJ{Nca*?R(Bx z{mrQ_d}a41fA6)y_4V3Y-}l;?+KQK~{l$0vZ|5!@^zVJ;R}NhA)4lr#?wqilVu*J1 zs+LvQ;98R)w$HNic8uTMVID%&E`W=6Ww3n&-Ebv9PI;sl0vrUkS9C(~*sDHp=q$G5 z4rxNm+2B~ShAFla4FOLh?aUq7XL+?gr`^wDR)-Km&mLoOo?UE%zbJbcN#~0AX(QGJ zcm*A|4HO84XiU#et!sD_F(P)i#|R#t4UZ&!al95VyCuLDbKG?j>Kc}St_qrL>(qp% z7Rqt!EA3JnWx4T9$TwF;vOTubMmKZq7JnOQLs!*qk-UbF4D?jT6j1$!eNar!=u`*) z8+!342tc!2Jpu)a2N;h^0OA24AmGk}7lFKz1WDH=dBp?3L;?^G0AStWkVz6GCC?92 zt|U3rZh^OCOAE|%tEDO!Re`T~ps(75+#Tp^Gg!UOZc)U-QLuO_u)}dQR|#o~)i*lz zf-P_r!crUJ;8yJrqUb58sGxK07Nbg2D2>RfL)DYP01;i23#3a7nJOLt1RVk5X?BIa zdcRYgZH_p@v&|s~1oc_7>$CB%*ix&EBtV>`sS}soqZ&J->j&d)eb(;yZv4z)3>2}E z$iJ~$lv^iy0HPkPK~#NBB4nRLYK;gXp}`zD6YQZRu{+SE+*VOd!4T#X4CuEG`t3^& zE4xmkBXBhvl%Z0ftTh0%-I&dcQBjwe=zS=s+Y|n@CmQ6tbsxR1fwoB12kaK=>N;*J z0z=TFl&-V;lrV=)7SywG$?2AT&~6qsfzx)vM^Jj36e^we+!nSw>TUq*TE9W$*v=c; zbTtusd(i!f?gI{!J%n6((Yty87~j0;9bJHQ?C7B`fWy5PeV_+`cJQK4^#H&~FZv7s zPFzFfBJ@vGREvzh*i9%Mw!8ykkN=}TUKBB!M7)L(rYc7RH3WpLR!G&^;9H+nmRc$c zrXY%x@uHIl_PQ48=9Z@0bZiNXAArKLaa4P7x6LtIEogHUIj7+iYj)-8Xw>c?KBnuX zTr^J80yRSfsY)0vLJJJTwZ7u4eftPWxEA@ zz0La>Y#A{tiJ0}4XSW1xOVG9itw>4R%_7WwRj2-3yTxgv@hn@#SlOeE z6@@@v(iX5egL*2{;c5qh&0%sV(Db*W7458FU*Shbk!U|U23czu-Z&s25ofT5=Ly&z z(pj_ACKc77DF2tLqjTto!Jf&ag%C(!UbPv&gDqcYie~(Qj^AW@yO1B)&aIn4NgG^o z;YVHVHY!1XihfWf!xQ5Mp4jTWfdEvBt|N|UA}^x(xeoE=;=%%D(eOGq3=;=MW0liRdv&mQmIEby^sk{Q?*rePyvVzx*hrWhv^@v zFbwcl)zNJH*X$3!LgqcTnReDQO;uiG-9irrb_S#GVW?V@$Ma|s)!4qBOX{G#(5=$XhGc*CdzyENgI-^`XYe{GfB zf!U+L<5K11M@{bq@LA}n`Y%?vD$92 zW$S&Qg!0jV;y{XYSTD8ND%GG=#SkuFv~s|~JqfdYI{}ssCEGE)zzBbq+a2LA?)br* z0@h%qghxhtr3A+nMg(3mQEV}Nr`SG`v`AjtLZ!LYke|C2Zq_fgw;_hIhhSvTK1p%3=*BxxhY-C93YHgNiGW0V z#po6(LE9c2w|vkRUyB5`V6j6mHweMaz$s1Nb#}7w3%n7tlI7fWI*O3)C>{W|62Nr? zJ(y%qX81*Ri!Kx>+YXEEe5~ndlbqZ5Hq!hHs1|>ti%hOW*6T9_fq>R{%&g`_^ zA{%BmX0(*jG}b*V4t#X2Gf>Ag>)1veNAJe8+!uJo_`L`{;Fav~CM0~oE88u$%U$4x z9YF$v2fPtm@ZWU~ay;OL5I&=;_pX0Q231%g2O}>QWh}V_n%J^aIrIcpN-M3Ug&4Ae zHgl+qxYk=iBW5D>K@w4Fa{WOWioXIXlT`*YaM8fgBJi@c=kzeacq!veE|es59-A(v zM9e*b8KW1{XJaN@XFwrE(heztu0K6!r~H{gM=>YmW<7s8@KaO2??JzItrvoB{%NB6 zv4#xg0~s5lK2-6A%OR-3sK*930B|O7ipLKa5}auzK_u9|ofWokXYz22W0;WHfKJE= z3{ZYLgs2C_(at)G?Y$rL1RY+MySzLF>@d6xcY(J0#fDr;QK~CN7u%(fouqcI%2iLQ zT{ECx+rg7UP12MHPPra<)|0r4a>M(QTxQ9)3S-K*KxcM2I-gBCe+2^eI9lbYLCtPP zZVWgYt{-Vi6MhR{6Mkzz_^pjQldX-~zVyFbT2pyxX%N3Oll7hBzJWy~+rQXftJz@% z{BCy}N*gU?bIs=`GUX}z!05b{DNXlhMkXIdrI~bO4xL@)dI7x!H%~$D8>FPX+!}kA zl{pW=y++ulhD>cRxskP^RzSPiz6dPid9iA;m6v1#2?4TUxECy28B7An*e@|`?&|TH z%!$xT1B?@nY~|`as12M9?)NC2S92I_xE~>16}cmvQuv?r0PqY2xZzF%*g>}${uvw@ ztuT;s2^Cal6a7ubuJ$=74ukT!a4Sk6rKsS4AeGp)Rh7Xo$COmY|+#_Z@UmVjCqxAjbt%>5?ufD5LAn2&AQQ_i99 z%z-$Jh4J0!GSPWL31ry4YXzDid<4=g!1%sS^z9gw-0&$#DKQgtas|}u+_so2t(zHraHj1>bo>q!9$vVZb1cu6@{k?#7YhPs91uXR6!7mT{Hq=7 zgcl)iZlxV=gB#SEPWV)K`d2yzu*L~52B6@sbPc4p!nPOwsaBBX-3ydSTafleZLuEF z}D-m8IWj`$mUMj(}k|0zrP_`)vK3#&xB*AG3vQY%pj0AgWR5?Lc z;8?Ph7gDD~qF0G08~;?3&|ArEv&s>f~?OVVU?36g-vE%^Hd8+OURKvij)jc~(U%?Bmliyg^-Z_39{YcnE81%Wm8YdAO*d)Z zek;(0SONsqZ#dC)a7$A~EI+P?uX1{`<2|#PjsFm}(QeKK3RAS18w{iDV^-lSV z>qX#kF5M;O@g*_iCdToTVmsp~cGWqAD|lrrBT$CeS$gyTg%EbVp37&s|UomsgvFf-W8j_TXtH1tyb{@&i-i0)E_oIDSld z^$kgFC2?)7*FbYTBpg!6iVi;*z7m3#v={b(OX0@=M2pE1LC+T(In0oM3vl~()ZTW( zPcjMCTnsj3yN^CyTzs01JR~WrvT+skY%g_UdJ&@dRvY<6gBK5EA!W^D)WW!!uVnAe zSk|gSDxWHr?}nPzSMc)KlzARl_CVe%#cxp01Nl_R#QS+4n>GUWOYtYwgZQ$EPv_Ic z_+bI3OK~PmL}|p2nD|USQ;Z7&&XnS{>OuUdi4XEYF|G+XD8*CiLHsHcpUr2B@n!*M zOYvFiLHueHpUdZp@iqbHO7Tn7gZMQjzCYhzj9)I`{!;ul^&o!C#1G^Litz^oJdnf> zAik0@30CA+6yvW;f)z=E6-*GA1cUiO)BwBa599|+aVjGoBnWKGR<((}FG72G>HCZK z@5NHa71gZY&j3=opW8D*Rt8D$o?Vk)6f}EZ$Yh*{3$CAc1*0aE1=Zr{3<{KJjIFEC z*3X2JT4KK!X$t=a@-=ALx)y`Z9t=cEqqw|xe*`TqC_r}B6^fg; z0C=FVciyqwE&qsKSQ(syIvA{r*MN*-i1`@)b?}#rzX5;Q_&I!x7(aXVsPRuB%_`$R z1^(5>e;)j6jQ{EIj~V~9@K-V>5HS##!1Ec%n!rmL$eF;a80a^Fw=pna0^H@TtdPKg z!X2!csbIdivJ^sZ3pStbp%F@FU`fJl{?5O*(2wqTM$f-XpqlXC>6jw;ZweWbe?NhL z(=YLpcOy(~L4T&)9Ff)ppV2aTZzjYfX3Q}JFfzU2;3>YqVKu}&5lA~xsVaqg@cRZv zooOc?0<(fl3gnF;i(z0hU?{aG)xm_V~Z4+d*q{>!J!;a-+hURjpacOgCZ2DZS; z{K_w2rQK~Q(@2E1x!6ZMG=@%mY5M-~ACU141h%<0&#y$Ap`*f+WyLVkC+zq*wh0c; zj^b<~qm?gUkQVhjUW+=Y`N&Ziw*kEl#Fu8G=fMf@z|S}p{@Lw?%%;;J;7PW1%VjGs zo2|bmTdk9=cF5AYh5kKyS5oNu<#I1mXgBx1p4`WEa<6|PWp|L&E=?7BX|MqdXMyg?y%s>B7wy4$<%!%8_7kdviH;`1U?HS|H4>YL4ZzqlfCw(t8S+ zk7L;ucs`_|z99)6#n2J?Tq&OunK68bIeY2c#GQ^p&aCaH2J^Yzm3<*M_ZMUXW^*8T zBfRir+n8nCeE;I=eiP03zp5^D0#T9f>`v9qfCZJ6hy@wPI<_Fqb zU*rdCmAQ8@0dxtI;B8E>0tqlzxcL=}s!%&J?~cmQRT~j*BG>)m5%oc5;_ienwX-|o z$s{o{b!H8NX7mE^^j0W-c3~(#4hlDe*{L>eVm#99_p%= z7oP>F3SG#xJ_#IUj0i@(&c;`EYB~4&NFV4zaP!NM&Iw-#NY*c;pvcr#=Tl&L&Q6D) zk^;PR^ddw8(fFnk*k9Y45dw2=eIhM;fpTc= zYA-DGfP6iJA4CJ1nxv&B8Li2K^FgNWWs;g`Jub1H@;a@@8{>C?Lw7(#-1xinK{VXB zk%bRZ;KtX|M{T})JR)oEQ^*7IKe`8Go7L+d!W(#BxDf0Ty{j1A3&<^C-Ks3wxwtXo z7w?ZS_XJhVp;G)sGyqr(p6Xg2O`mt`X-8D+!9F{L&<4@V@zYnLu zh3Ts=X>rP^%y7Nj{LzL1pPwJf-0D(na7tLmGDBGb`y){XtLdupq+}g`zU-b`FR;hI z1HGXQLLuKx6o;J%&_D|#2u){Sc_V0ELmoJDQ1&5y(Z9ecUxp*>yLY0%HU!3a*O-a?MZ+}15W*AVvL!uff&sF7Rhlg^fbGLwt&5(9nJ${x6rY~ zmWee)i?+z4vCFD3R#ARbg6Z-!8kpz#r=iaLOE}shU+a^w-cVxHT||s6#Mmt%#+&;M z>EQaGd4ZREK-++`LS72c4*yvwV++o`3OvUqlTyRYp`ZzuG%JLoSk`iB zZJBo|l=(plXmPC=?l@?{9$h8S*2AFU;#h}HQJtinl91hkT%+}x+{9}fUCh>CFv9fy zK8^DCG0HDZXK~2O2n?K$d9dPsKiejYowPl$*K^zfH-uW?aZvg;V?YV^c2n)wAxl;0 zn}i^&C9f)jO5L9zsuOrE19MHX3HmuYz)E-_`4C+m^n#nPt!smgWYK+eT8u(*-|q;C zf}*d2j(c{EZ4W#VzUH_$eurgQ&9XQCQM!ZiNjWG*=i|p1=bMaQL&iDa4%&ar0_HHf z2kre*7JmgxgedItG3-V7HU4t+nvTB|p=N=pWfliSih|?{ZGMEx25n?OC0L`z8he~a zU&@w0BRt{J0|jGGU)8naeiQOXqi=*M|gm9%sKoyu}5OpznJ)*GB=2iy7e-+6lUl<%JMxZR1(6StB z9A#zDwr-Ger?WL|&wAm%A%|BP1X0dCyVkp&Klxqg9VrVnHg+t33T$Y=SFs_=0K)bF zEQi@q{E;r`iBNC17LXqSanNQJzI|~@=dsFAzEwC5{lN+CGx4==DOQP)vnu6hha@02@9K0e* zT&>Z`ku<@gEQ_1Ymr5r#k(42~+fD;$CqMiS8Y<_ddm8FH$(ZtHq(6dvR^`<2ft?(t z{-%?=MO=4T)sG%^41Tmnr3kxnAq-OBrlxU)<|Zbqu)S$3N{%QyCdHtXj8Q1ecT%(K z9e)>6vHvF)rP$$x5Pz2fxlXdDXQ$gllNR~92s9rlG_&m*$0#yf<-vTyl4Z;)N?!wF z^52Uv0Ze3cyJ*ZHh=)w3P{s zHPE3P>Y-}?vrgoTli<2+hz=Npe~zE%E%*t%v1g1;hkpTYyncWusy9O6 zk*3D?>~IizmyXf45Pvjy;Mmdo5e-Fu(%uU;xZz5sLI5b-aF_w=i36Yu!hrNe8|vVL znn&et7;ypOphL#jqF&($as|3bW_jcpSEK`jmNO0y*G|s@WN98x>{zERu`9X6u)Y^1 zqaC+-oIQ4k*pglO&T`R9>6yJz>6x_Sn-a2>Kd#uDhf=3e8T7IEE@D||%#Gn|mcY6i zDj^opdiSyq_1@!;?9=6oU*0!ue5H=BxDQ9~D1RL#Zqyw{hp>v`pUH zmmb+SHKnB$d^^t}ufwUZ2;#ZR;T-7WNo1pF6}0QHO$yMR$bliS1LOSt~XB8l^vDr)rFKd z{xzgVTmfooWk-2CkJBnongn~f2USGSlVA!#?pfhTvW!^VsFcQ$N)^(@LM9C$x3j=y zA+L}w6*7-~A3U2#3rSO_XX=>I8YfApR9c!CjIt(7Y^R!nM}++`EFr9#D+ig9YVxNH zVNxIe0V=TpAu(DmP5zR;8CdP)HvFOnu^_Sdo&1>uW*DffMtbZovX(fUmMBc(3{*~( zC@lBL42^;%T`nfoVW6s#trd5q4TX4vpsHU7t=C7J&@0qGKsI8cN6bOK9zV! z^E#Cw>8iY+K;>#eA&6@$tljxQJ0>TjJ)Kh>2zgcaMt^LTGJVde?0D7}tu;Tg#?_zi zyYDRt{4Lh#C#>%i&b9k3U};@t`Xi93K^TaHAB6|90N=;pTXmI+&rXCtj<9fkrjofz zC2Z%z0V4hy5#`G?(2f<|o8w+o5|i_7^Q8&T*rdzqZe;RHbAN+ed)O~^EOxDtHEMSr$G-&;h zd>;Wj0APB~m)I|`8d7Ev$IO`f&8>@4c7At%dG7C!loAqs3ZDA*Ot_XK35JmIwU&QJ zvk?C&5Mrf2hUm=Pr}4W-M6wcW9Em?CaoW1_q=HE?j+xs^k58amZ=Vi7gG@ECviCRN z{`ljMd!nPDQLTX?YxjAm7Bq{`A`!06oH__~{d4f&!I_q}X8Ih(9h}|b=OI>Jr?`Xj zTh*eiI@(kI5@Yc;=4CDd>8Rm2hA($MJ7E`R+v2rM`TbU5+{!vqz9i>P59U+ZV!|Bh zR(}qCl>ld^O-Eykv+KRYZk~n6o!vUtOAOosRSwq7M}vuI0L~NRpf2FpCh;Bi12c=D zCM<6C&J?u%ZlblwWlG25QHrO6DYY6RuadxIZ{U>Pz}DWtdIq-GEpkBXG2KB?W8BH6 z?Bp65(y}mfGmMI_1oe`DaNM$<^R#1EzU2Bdj=UG1H`*h2pABBF`@&aobRT{mINKQe zv8VDq-1ci@ZZKP%!WUZ%%$wlL+_B(QU}JsxQnvkX+1Wii+5)K2cO2_gC=V6LJFRit z4Gf%0PNwxXI*{wM_?s0pxrJ!b28|#3xLh!i_NfDG0%DAn*?o>&G{ih@=Hce?jy^1~ zV+`xY&vb~pl>>m==sheE)yWi@ErAnnXrmtQGU*^Y6OdjUQOsC+-rb4=lMM)>^CJC>|a$`cDOIVw_;%HS3vos3u{1spHL%d z)f{;8duU?^dn&gfJ^$<$d4eq&kpd08(uuwb!T1x6!%ZkADZSDpedQz5i(|%9zn@NT zFC}nnT6VFOO}^4AE9Gk*QN*}@tXG4<=$`#aw~e8n`->l?lWJqs=XRU))yv>cNgEQ1 zeAxong%Kv$vv30>r43`Zh{P-EkctI3QG33~SPr+3a*mssPG|P*mzmn1{2?}FxF5C) z~7FL*-!R^GCllWC8-qm;~dWIw;jvz@hV$uLP;gtlwrh{8DxzV-E zn~JX2k`~}to#0qXGSiWs<4JF6ZZ~oV-a+V*G)0rf&_g-}UQXZ-V6tzx70kUb(jr^z zRLJVv1F4Xt+5>L;8)W2CVt|YE91Zsb(gX9d+k_xHx*9I{c*wd+o-vcf(3kDt$|ezL zNGbp0O6W=unm-t!-vpudfY<(45-htD($ER%U3xcx-nll2#OZ|)>sRv8l?daWGKt1L zW#YgEW%fm_<1%>)|ARa$50z&n>c3fdIXrhe=zuT^Av(6&JeN1|#bx8!7Mg#^#2>OP zz+1A6y;E4$VN_D*E#%XSgin={5^ng_;nTkvJ^=^4&=*43_dCL zeGB;R!ral<6O)IkXoqh`@@tPv>FBj{@GZOckWq9{WiOCV?NegT8w-Q6$ zW)Z!yQ({Ss30JeC{R=XpI>$+Zk)=q{AXt&Pd;}zDl)U(QNhqLhmA&{rfVKMO;v!m% z=P>&{%Q}($B;p$&IPmAIA?2noPmI){8S*`ntS37jxc++&h^wFLb>DJG&tjh`<;^yy z#OJ|xOj@^|*2b?vp}Io#dbWQ`pmYvGkv90`=CL1%o~6%K!E(jTd+WI9-q-bwbG^#raflJ<|JpmnWd5QSShbPh?{@&!yU4^GPE^C17{SZ{7S zzZnu|L0h5 zZgWrsT3=?R(hjJ)(U;Ig0U$@0@6nljYPugO*oWjeeuw;p!LN>;Q8!;RSFpu|80ubStnCJ@}0Kb&?qdS49o`L6!@YF_4yq+r@g+#Cw(m26N zL2SEH8zBsJnOe=5(z-&ry@nC#_L#(%+8oq@j}lSbcwQ&}@XgIKz!W}sSw*sE_-5Q^ zgyPLX8|08T%oz2f3giRAy@j)=(o_K#4q7A!yZSRiSM5n4_d!&p+zgCwWGZC#h_j^u zglt_$Tk~xB1_1Vl2_iG-;U6L%t+0g(VRS#KnH^m)+BKa~43L_2%yC^ei0 zIXFttDm+g>*rf`l{Jk|q5B9kWlG#$zrOE8nf@ID?k~!p+FhJ_ILhtamh1wN*e_vUn zv@8EwzW}w36?Tg)E0+RI6SKdQCk)DyL5twbCvbWaZX-QsM&{#KSiJ&EUwZ6HLv(_k zbiZOe(s87zQa^I6-v|GEwz)PLR3#4^6~BdIV;))&#S3-{_mn%Jq42Y8dd1_ZxqcoK(LV;P_~ve!Mh?YNoTNco23Z@X zrAzIGE_;=5iJl(Z6DA#YQzad{Khv}0;Edn4ZWd`m|5MmhAKum)a>km2*dYWhPZr=nlF%ZH6TH_J z9BCj{)%a$%8qW_;>3Hmr6l@{q zBne77kj9MM^wz@IS$C4+DT2A-Bpv{cO#tFSyWqx*Y>y!hcilCyc=p)g-=UQ5Nd%uR z{xl%^bn!z@y=-?Qb@VRj=xxgiX2F0C^v5UY#RCBLc(pw70I(?mh)4D;u+J=Gz);{c zTs*>pXLY#Rg6V=j|4{44b4ynNBBx8RUPed9h6A<%i$g=t+GVHX9qoEo z!A?Ze+N+anJX1ktfUxTk`&g16G^PK*FvOrXEg z?@kr~V)Gt1*jA<$$VtOjGnBNiPnckHHhd-$$$$<5IL!g{2tgdo=ZACg>7&+eU$zGN zGwC@D?Ktr8WEz#(2KK{jF3~BmIizQPpRjfx+c*4d)Zyb8AlVUhFz+gnIPza7^Mrup zBC4REz;g#g1YSI6#&?2(p1l{*C1$`S@CftDI8ryx?d_aL_XP0ZT=XWH8t{THQbun? zpv^qBA~Xh>QlOJ~eDqe~iV-a)=aJupdy2@;mr+Yug`*46uNxcY{AvEUZ2ZO!nLT?R znpUiPbcf_0z*{_sFo(gw+fx}6Wv^dTb!{moGL_MNnaZktW)*ou!Oc`w1G1(INogi5 zYEsi3%ZkbvLNF}TQBRcGY1!67U8z&!xpVyDgl;7RQjf&8B5AvvHN4h3?mV>Jc6(&X z6AG$!8NNHfi|VlML$Xh2$d?9fBFjw|Y0<&{1+{_=*k$F*%CN_-+NCMXZPj>uRnp8V_4SaQ<1?$S@7ZNg0jj70M8v9FqqWanpwlr9-KagdZVq^?q21eV9lNo$O}Y zSq{aIiQ*t}g8ok2&KLB{W|t&}LQLt)Qwa2+d-=G9)E_iimkL-}E|2LTrAP%I(M*w1 zy-sFRsFtBK&bmepdtk&Hp+kA$_sEqO95j=o38>p~q}nQd@BqdNZ5P!R!pDIm>|?)^ zX)cMwtEO%U>nsoLX44VnY6Qy9i%1qGK0IaHBDQ*3w=A)RCd;{`(}j;Bjp=lJ+mbyo z{0)BE8z>=ov6V&q8i1_t&HWHZc6_o@YDWgtN0Lr2dL)jEALe*)6f#w>a&da)wr1gn zIs{Fy6g`5-iR!=fAdpk<4!R_9PXaz1q}lH8fnuKR3E{~7A3DX}CQl6pTsLR+wVUvZ z7$a>Fr11=jU?j*MzjSc@D9EMs-#uah0I)pytfruW=2& zj6tayO4m`|7UZaByoPxN^3m$4P=ujNSWpV&4C`rdarV&pyB0pQvUMBFfHkg}hb|j#=(F{*E20)Z2Q?5w zrT~`zP$+QCL>${Kg}+5!uRdU&WQB71p8yQF^(X1D2y5Cakzu%5H&fdbLO7l8bZkF* z4|v(=hio&dCf`pqp!PXI-O+A)m{QMT0+X zSea{NczlQhG;}SS`j6(5;-Q~!2NjKs7ed1gCTf))QgOSpCnUq;QysMxBMq)Ry>&Wi zNHtHu3fy%^U|QVzAqXuuC*u9!Vq6}xcB|c;qsKfY6eAkq9F~sWo`DpWiWs0ZHXi0$v3SxY5@Ep?uJuf%DcGpaC|-;a>qG-Y|3lx(@%?tybaR zR{X17W5-v379E{nCF?$*g9Q|x_}!g|{!CHZ?SV}1z*VYx#f|wmSFv`hIhuI{7;lWC zNF!y1a&<`x+R<&g8ir@HPNNu~iTp+^#=r(W_d!KyEBDVJ@=Wp)XU7ZX#qeb)LNv=< zs)37dHJqXM+qlxZ>_iD$(OJIXGWP?_mN4JFFatx3*$r-HSIvQsR;KA9wn?G#VKrf6 z1p5`x!(Jnwj@AN}$){&$`f=QZTP_%5^C=wIf4@`5Mk-UB-SAe7lzc`#SU7IZuk!I& zAugxGlD9sP&qP=~1$gg>`ng;$mix}Ob%C|>?K&jdXrhNcByA*p5sM+~Eb;(j-JgM1 zI>%|}hVI|Ydf4Oeu)oq@D>zt1mgex_Nwo2>v*11W{5fDPqg6B=x`ar2a}z z>PMNnVu$yF&=6hUgPBeSm*5^F+=mAfZ7_di){X~J&9cnMv z){9?k9m#b9#|UihSm&@FS$}*GJ?Xd${BeiwTEE!b<>$&`B_r=lqS*`?-_u#DSek2H_9>l@vADSidAVo&7&1%^Yg4q)+FM*wVh zM`i_A|H!Vdwa4%TI{I2U{+cFYdDxZdWY#(0Lnu$yj?za&qt@;;#a?{%k?3W=LN~$Y zm8`R6Xyb8CqV{7>#`crfX3tyNKrvxh<&_#&~F=m}G}-3cY)DuC4-+jTFhtna>oy3G#X2eR?@ zzu2pE_gv~5+>3PXF2M68R)TrV%?26P_B4L!BEx+$&ZX}G z4=@Jgv757zL*jIsj-`k`lWADX&=E#L1@BW&3#k#LBO2pDjT;_>}3 z4V?9JHC@+)!&j@04Sr(EF%ka(WLPf=^dQy!AL&Wh5%cyGs}*wrM-!<5BxhM{w9#^- zSoJc~cvQ``@$w4oGTeO~Pr{h?uOW?xivJDc50PM9p|%U z3NRv!LKyWsa(Y&cKJs@EU6s@a5h;7Ni}!Z%9UieAz)D)W5OhB|vk$OgP?oCw7lg7q zlx*1twOh-_Is4Y%W2oB~3w{ZAnD7!=u@G$9hPXW52`GTx&iaVA89D(w`V4xh=Et!& zzEpvI2alJ1_%WSgHJ{06rwh=}MnK8tcVhUe3>}0mnaU75;UPQVA~qXlFAFts?L-2@ zuaSW~70bJ0=-iYcg|WR2Y@wmSCY&u=<~qUBX2g}M-zB}vk3h>-^^jfgch+MTnP8xe z$y_=4<7Go^mWfnVewxe{`OGMmELgv6dGl`{f7}RbauE>&7qg2ENoSPW%C#eopCM9I z^2IYUb-B?es4Wz7_E6rm4OMs57qH-?+7Lk_hn2|;x|>?5^ni`!2_o1>V2YxqB^#ko ziG0fS5#Zt42;V5huiO*qpz0XB;1nEl7WYEw%<9SmCjvx^o&O>n&fPBWS?RurQ>^67 zZBvNQs`$H@zLs1#6_t!u9b%oB7?W^6h9R%dO!q3QVO~%y3d<`oTW|6_G zufStY?D}3YBPcVdqazE&3rJgt>f>kv#BbQp%-Y@Qn|gp_?L-|elsbG_(n<2Hf3xm6 z%}$-@2_%;WKPeVdV?6-&SL{f5UCDy~mx+|Y-}!Wx=uF@X@73g;pti-P!DX<|IA(}= zIP1Gpu2-I^E*pJ=zJ)O|joZk5851M>2I*6Au* zc0|uR)5`UC*_wz9d~&Zv<80*Ex0k5ZIMY z*+45bYspU95%Gp~+}B_V+1FT##UKd;fj55Y8Q}Dq_`AraChN=P*jIwBio0*5iI1k{ zgcr4xoC;#sc6~9vb0X1tWsPZSW&4t(>5SC+%J@bpcC7J@Qm((SS^$re>a0^eG$U%L zP(>>a{k9JI>R1po?tO!=KgXTDvGuFskD^4o^(%yyFthawK<(BqdAsjx;1)+*2F9k_ zbPy6GGi^Hh*83ZQA7$j{yc9PDoijtlqdbo;*5fCBKJ=ZcF(o z!R{aMd|>3>56CcPj`%*A7vXd{=+X9uZ|*`l$mp4EFO=&NU+N+9>R2xV%>igmVc=ey z!umV@REMbLnvjp}fQaW+fyld&FR7?)ojZ!QfJ`hC&5b9Cw#6z!Od`Mrj2h%3ZNtXY zczSVrooHx-=@dEF`VD?f0r)5~0;AJyI>7Q@49&FZ^pd9g1vntKE@iuuMdt??}~g4uC&#r0tE&yD{UX&e>hkIZul9d z;`U8KI7K7d2$RVjGm7nI9s`Bzww-BJSF3njcX1;9tThGScN9;Js9C@7J4%W zm(7OA&o^VjzaeMePP;w%=yIcTNPG%3nDT+Xx$m;pj5n!{M!4amaRaPz1B^G`4h)qX zOdXp2T3{x5EF%ea9@0n%;<9{UqGSOE%H_$8BqisN#VG~W!KtTX)JNr*Y-DQKFV7?l zyV~%e*x?12~TY_1kOE43>05jKK z+Aw5!eJ#SZm0Fw>v_E-2Vr=ren;ry72`L;tCB`#o4&w#i3V@)goPYPWir%-Lg`q2K`?wX7fQFeH~U4Z$b}&JDtT+cU?a1PvecrjXr+-864Y5!xEdmsRkFX zk5$H@WGBKJyvDm0C^-jv7Cy{tK~vAqeGedrmF%~i!r`%bR8Oe1^j&uhd0GX}`L~{k5|C#<2ph z47Asu9-YBcM6zNj?pK{E{60u4`kArtb?{`yrh%Vbcq!be!$gq0UK&-@w%DKbcEgd1yF@gsqBP;p2e7iD;E&?f(!bM&(LZ@YdY{^$Jb5Ug;h@N zL|4whG{sWIrcRzXxdVkx`6!{ZzlNu2Wd4@$$o^UeU};G+A|`a`8YF4sMNnyM_AjlZ z96@e|mWss+=i|-)1aIZ2q?VLK))E^Spi;dg-2lfs-s1i|_R9;M^sMQUk4ISMez5*l!Lm2pe2~O6hG+v&n8<||Eq0W1C!#G{L9_cIVr|{8iIcUq) zp4*dUbn-+T2AL!qaO`Hh>u|VMj?h*x%^k)SfOkTN)(1d6JRf8bZRkNXGC7_gYEBJz z5e4RaFI%&*f;9U1JFtG)E_EwnvczEWX>@D$X!!!yxv2SF_y?ue+Vltb(Hkap468W& za;2)+x>QSk1A9LxZF7b;;PxQ>V(ah88+%oQ6DycUR*Xr~9`b1YO(@ zaY`H0I9lPN00i;u7uK^$SS@UMqem}2O*NIE`k6h1)i;~KdQb_onc1muA%fBrzSsVG zvULDIi0>8Wu04T!u(!JG;=Hz@=my;FfG#H^`;RH;jxu~hN&FbaYLIP zT;ftlX{Q407CUc*nJduqHu|OtCY2n>B`Nh>KZPyDsSOF-WlYDXukRd?~4F3;pNW94eYXQ+6_atXVKo}4QusC!ql3t*k%7D55m#Xv83 z!D1kZ=v~b&fGxqiXf@lLcmZbBck65LEYhGR8Yj#3X{52qf0q?(l3P}vjOKb`0g&bE z3U(nFaI>CR1n;aT61c2B7vt6?=@Q%uUW(hm7vb(MS+%T%OV;AyR;VUZXNB4cv(B(i+h(%q|V6Bu-!wegG$D7cD#7B9Q1=A7gGKKn*R7nUa({gO)bPW=p zl+To+S*&sLnRK)pE|oSIDLxZk9Lu8@a9qNpVt{eDlAxUr?swK9VS9!M?Ix09vCvV3*RmoVr7cU2V%35gfwui*w89RC6yjVFR(- z#H`CpXR4z3(K+n;zL;FfdGn@MAfvf$apH?Reojx}YV<=L{sWw}2xkfKTI;fsZ2Nl7$(a+?pmy)H&yd8xGo7rELEEOPq8Rg#*R**8+2t9 zMj;f^+Bx`)4P5Qde(eZ(q}Es#tr*2`JKPpub|m3?(OH*x|R5XvqCN5Z}`em&0Ad*)>IL)zryaP(hLFu zCfjwK%1N$Nv=w<3BUH;W=!MC<$d2^5lwJ?;>Y*y=_|(Oiqt^uR`2-n*p%*b*Vs~M? z(K_FveYtuF@`bQ=nR7fFEJTrCPY z8+h}T02W~isiP3i@v^n%5~Tot{T1!fxzkb_yZ{Rh&|t)$QS*^?GQjyTOTqb@i=IMi7i*cTF~M@SGP)nf z&2j1#P+68nbms6S)!V6wap~1~x;J0@D`OcNM@cczziAQ>=D>C?po^2}94tSd;{HrZ zciol)6?Jr0rMQOMrd(X%mcFjW&P>=(b)AYAmRr-(-Zgywnl00Fx-w$Y^se1B@ffzL zlpNjeTBr;!7u8`&Wnf9(Uj1`XUR5{~m1x;WU{*bMnb_HJG*NPRql&nuTCM@`db`vK z_m7RI=Mr+d=M-Y|>ws00j8+<^{Z|$D<5ZwFqHwbfC?c{S+7*qjGGmk9z_n$cdwjjj zD;W%(twa5UY42Wdl77KHVb7lL!uU;BNcW?-j8=xa^i@_aDp~uh5J}xT!6JK~CXVf< zD)_Roh&Gz|^3h%9_tsdecCd06sppFjFV@nRkM5L8!KtL1 zsa!AUW(z>3uXOgwIlnFL6vSOJ^>hm9e3T z4{7Feqtg(l+DUjX9)rh1xq5<~@)2xe!+dFMChyOjauqCuI$9yNLUh30`T^8V$K1_t zr&pH_*e0#-(337~p+1v~g^SD-4mH7xc4P3;XkKdbuqTR}dpwOW_Zt{wRiTH{F^}TT zUzi`jh0}ouLL5Ab$+{;8LQ6ByA}+z813Z#(Y%_Lqo%(EjHT#9^Eo`|PUVM!qIAx|aQZb3b$WxGu{2NlJ%q^ApL!{!39_K5i2=2xjQ* zikxoPO&7zvU35uIw|g#)>UNQCInue7DQ8ia>_N7;J1&jtl;hy*^7$2}l`*wY3t?F8 zKcRBUomSgA);sz#FNdJ)OWsZo{-B$%O^0t@k0F+&!iOzK3J2a#(;8Obq9?12s zO3OWGba;SiZ#`M*0B6tfUVl%r4lde4hz;o}paC+IPwBE?8}1S|M+fjy^+mEW*oKSW z1MWqxtPQr+vIDpwp1NpVu+7^x;0>hk838U4w($%gW!(fsJAq4k=-5`Qt|6D)Iour3 zt5o6UEjA#VM<#V)_+&227Q~Ir(4;*RF{Qa@fQ0BYcnuW#D(-Hs zG9l*fiHNR7Y7>SsyL>`ML|1kb5(l4iz8N4~KE#Dl5>c8vfIEm7*o50!DqiI51|u8k z698$ATmrDHVLWxv;@meu3349teS^m^$R!I)>c^+smUU%UKh~j=UwDwAbOfIo zl4pHfl;@JFvo+!knx4s%_m+YtWY}0OW^Gd#bTZL$PA=z-IL! zglKQ7w~4gd=+;b8pY$rq8<@6Qr*o|3I`uZ-yNctGXftv@k!v5bpvO~Q9>i4p7T4ss zG`|ANBlaCQ>>|mY(pDNT;3oZXsIJ7zM{l#q1r9$g-@WZj#L%)9?{cRr7#_IA-T9cq z{@N-#Tm>#oNE}xJ-H$>*u_761zNEhyh4wpoG`1E^fvJVdJAAH5Uj*v(@Q$+fd{QfQ zR+|HS_!WKOOYAAEmFfS{KLY^Wq-Q-U3+N=8t5Op!AJXm4Y;r51H=kKSnRTooOKp8W z3tCo68$5=3;DY79LDG^3VlW%HjWhIepXgkTO*)`7Ht4+`UiXx-4_gXe9V0m}`{4Mg z3xrjl9{vP)>lA&w0gj^6I$@In_}`pVpV+`7^JNCZ+SO98&aRia1}WQWkSmS}uqkA< zvFvq9HrC+@Te%q2Sjpz?0Ct z?Vrl~xb6>c!AoO%&C}~3klkN_4%{5@q>b?kE71COI)XBReoED&cW;hcbGYo^k?5^` zAh0q>^CPxEeW7IqzDtE&Z|wDL;J9OwT-Vb`jTsC}_*9UHuhDZh;xiXbh(Z~8_8@v} z)I_WDvpBjkXyR3|8k^BuH8&cOnCU64JawMl$HdszDYjdJlMjlD3$RKq@g_i{xxu`g z3S2Eq6v;N`A?A)`%=t9r{hC9_1vuCsco=Q}T1NM{` z;=NcE0oRB?iXvb>ytG6F@DU(c;e}RfE{9fcF5+3?{k!aTc z_V*$k+~GY9yyIUCVKX0GT7kmG-|d@kvX!`lAKXy|usACw%y-n_FUbenOk^DZ(9H3F zEAU*4w%ChHH87OEgO2zsBM`40l)hh6`tTf)ygL?Q+bhWW!&A@Qi$T}5BWPzZB#92d zsh^&XuyP1W5!B=$LVpNC8$Y=86TiM&;V~rXw{aYV9u>%^u`=@F$)L6AFIlriNoB)5 zN$_$c(1KyH_dFny^0_^x6g&l!+GfzIRhLkLqkJtDn(KnJ zc6EFF0rKi|An6V=rYM~3Tt8C$B47b(Knb^j--# z66}%Ok``^|@Eb*Zz$Fg^pT*D=;NJY_;bLr+cd{^-^L4EFxb?siVL}bCiGBeQBOm3I z&oW%k{FrLCA<^783vnVGP6gT8fFHdSVVEX_e0kQ7?nbEbz4^e0v8%4gfrxJp+19W% zx}H}ux_Gh5UxF9&w&KO{q~QI)6UQr6-%8@ecN%?o(x~W$r_zi1IM#73^1^^T2${vVlcaGb@YPRmNWB^5 z#7F1x{XpEmL&w41gdoMhGJ@~45iKS)LA%mUr!*TPgoE>V4hHW)At*UbI_UZT%!=?l z!M4^}r|(jJ+E&Y&c)h*@!#bXgIwrjBsiRa*iNHC#Z))bbA=V(?glW6)^tN46p0wX8 zYxN0Qo^Y3$WL$8pwI~lmN=L>Z4Sbjh?^t;uo3A6ilJQJt;!{-5DpHV`1))j*1m`}^j3%8E4OY0PH55b3o)L=ujQZu$-`&g z=2lSl@TGPYu3n-pC6yxiGK#Z16tz15A7!uwS7b2!9Lf&7o~HB6BLZQk5g?46Mp#x@ zp^|o50RB!3cx63c_oN{_Z3tLagF3IeouAv;;aa=p!e^>f3@<0uvE8}|ErVEt=xcGw4PvAJwAXtQRPt5T>Be0Hl zb=-A!Vd9E+%{HE-pQOv-y)Jx2FYeobH)61m3GgLV{2#4^Hz!|DEpGU_lbELR$+_d% zlEAQ`-<7(k`QvkvX|VS@FW8#sa1{OyNA;r)*sAET5dIDel^eb=Fj|As8bg@xDc8QT z(-(Fs2uo#-_*>qL)^)-cB6R`JkZtC2IPc0!4z(s8VhHZX5=G~RqxqTNJSH7Z=@Yd; z{4!wca}PAU!ENVHo8(V*!apEZd=Zv5$hq2Pm>%cu7wd6|6W=KduLGt=z&i~t4kYo> z-@NbQMZbYmX(FLN1S!17Q9LTE|R0J|wm{6kb6o;NBIUec{{fu!$JTmU44% z0X%@o@6~Ye(8Sx}*x}dl3q$HbY^xQ#O>Ia9)=<u_8HLqB|pek=iRXTZJ(9J6m^1UjPNc<-6dyxrXI?WSV-{al* zmpyqIA&*U&MB1xEMSN=1a`8HKymOPCt4GO*NEFH`Y3J z+%G%FrAP;>YgEdz?EN4vLIkW3AQOf2{Hzc%J*PFiB(#Y=$Q^} zPOJzx_@<%AqKaLA?Z}LXA(kWW11B3p>FE7%>$$Ypjych{5i(lbKh6hTEv{ETDs?}w z-UniB?7Xc%CDF+;)@kRdpD|CLv78D#)X%0t?rzrWT#$_yuVV1n4tIle;dAmeu}dIX zGE?#MTMsZzOF(1Dm83ZbY3lf**dr3nkX(*mfahG3CO1VC3@uLM#b+`ud=W^vD-8v` zC%+fpCi%`|zO$js_r%$)>j53cn-B3DCD9E`bk4#={NUL)B$kO6qv-vDm=2|UaXg5y z5)X2$aKB2w(p21_YF{(#_ZPZ zC|aIQ7Y_g!i4-6n0QM#T@c?jh0uT=X&r1N}0pN}VARYkFu!>YX06aAThzEe@CjjvP zFp~hp0|1*?zM?@-GOYs6$wz7+9soE42|zr@+pRMI7}EDg&NXwiJV7tB65o$MlR2)y zek46O2yoi;*x@_S>{Yxk{Y-?qUp?SgFKz^6*-s+0nHJPB0X9tU1_lKc6@=1aMje4d z#KZo4C)(m!kbBe4CA8uA0j$6``g#&qwOh|XCK&0rs7%xYwC*s)F^w4N99_}quN|?{ z5zz>|=r14{1$U+1s;g%dS$2LLDMU{G5pv@6%1KcUN2scg~m`6Z9=K1z;i`ut*thJlsISlkQfk__=|w_AGv zz`AgxeSsk2FWyvldV(Xcl}(ZjwV9rXuAzIy($A0x9Pz)$corlc0G>j?9%mdaY^@(~ zpzL3V`WOpYr!CRgT0I}hO4HT*9h{twIK#8eAtY1gHGB}vfdoC6@geqg%s!24eFd^QC$f4iqBj3MgQ}2u4$ZlkuZE5O zg_!WR2qQ9Wf}yR6{(C3NOjZlUT?s&}i%W~3a-JCB!rOj{)>M1 zG`S&L&n|~-xLyihyo5p>`*;Jd94n37E5I3y{QVC3hL6yYZ+edm^TF@BJZAwa?wh5ANhV29n{$aG`2!^ki zb4D}cDQ2SUDgUd(IXdHbzQ&pjUrWCzJ31WdbJA<@i6unvyBgnzTSF2KcfhorW&M%e z!uamuvphX2$lMyxr28Hci?3;g??NUg8so6eI$i|YWKUE-+GHvtsu&MprD{=ysrBvH zm^XVPtX9AQ6U)tnMQMlljX&m%#+fw)&N6#zU!2bBy3hVKROvZdc&8_;!;XxxZ2OCW6Ncb7n5l{B2Qs@6B!W&s`^56bfK zpd(OFbR>Sf2%if;nX1o}tEV#Hz#6Sptt64+BLMIU6Vh7&>+ZN+Tsx!?u=?AC>B z;@wXDI=jXBp+0K2&Z4_g-3Yt5-033BZe7NhBUFZ%@@$imZjzFIyM-xEaL|ozq}kI@ zn|=rvON9CfI$#4NRFDo9&^S(K>15WfuY>3}&{tRi*97zsz zX!aCn6-kgv5SIE1SCuJ*e0Xi8UNeRFf^Ygc1ZJ15QTujDaXUE?LgcZfD2caI&)RxC zxQ}y1yi+|SnD`ANDcOrxV2(9(pz_K7__H|{v~C5mfX|DCN286fIc=@N<3ohvt6Z3z zYk}uaeU&^rSiWNpo6ogie8VxnQyxCG5`F|Vm zzdm|*?wMz1o_Xe(XP%jH`gmuq&tuBvfy~avrf@r%T7-c(W_Cs+Cf4V(#ly1r^y4M9 z`fGnX)Awt+@zM4p|LhCXQ|Z&l|O1ttGc@V3&siU1x&5|lXU$fU;2mMIi))&W37ur79Gh52jEfeaC)(R() z952@6%8jiZIQsy|V0YtgOtlEhP6Kf zv$eljP^iDm%D|eL8EOSG(F(q!o;ai+baZzZ9(g(Fw_N=xXR~=%8@xoj>Ht27`2d|J)8Nn z8wML-+QYHO`3DlQzxeNz;c7QXE)eG5N#mi~p*X%;lF(B&+(&x<26 z-I4Nm`P{_`a;{DCBRRV?OSZq5iuiJdNaM?~r_4+~zgS}3O3vE=6;Q@krBGJ?DiIY97lr2+iAceH9Y<8+B@m&PPa-FU7XXU za&$!V=c;?UbJq49Ik(x+?KZ7eZ+ag)tJR0T&5w5`otN!kR=d5+J&0j`?3JNWR{JIJ zlD!}se>q^~)_|3)e2%&u)~zJMk=vSkG#Wcdm=lPu)sZVKx1A3K%^kPX4X5xaZ`PHTKq75B1w`FTXCH(aXn?b_e+D1yo43!mTDk zu9@hmuVzxGq^;<}z}9z2jKXw7%tq)Q_=`f5WiEV>G6U;iFQ#(qHffj$xNrW7z*#)a z2h1-9TR?rj-K>v?)PuANu!)M;M29&^8HlxyQ6PI$Rk{$7Vm4U(V>sdJhQL_$uxR2Z zUxhATg~7_p<9;yCn@+wXxBVcE2<=lN3~)|X z^0ji;m3tY#+_mUWse9#CMtfx%5E_zbI=QC3QN(3aqqEJ0#E1zzxpY>s%I)as>%P7j zfzCn6Ufr7VZK_@^aOFhfiNxV*ic4eVp2~L>)YYQyV-0tBN{=Pn-Ewc?<3JJRom7ue zq>Tx!L1JBd5p3v60)OK%CF_&^##``z&T9Yp>T|Q;m*UgLyzf%(a;=aVs@zUnwFkWh zJU4D!tU6@lj<74%J96|#7;ZaZA-$dLXWK|~ZEU2_Jw>#E&bpkOhkV9G%UEYPK4NtdMUI<_fF=WK#( zBxpl72bl!^b2M}0RW5wnbFjf0zhnIEzuhK39By^@Ww<7FcOo22y!NyW$swD1u%Esm z`CvbO&ZMoMzdC+GO>iO4sTMozIiWB-uTJiP=vHC0o<$axx# z=_L}`oTD}mR73P}6K3r3pcW6&6{9qY0g)R!Fz-gsnqoXi4xG#Z?nL=$vm8I%j~PE5 z9@sY4^8CTV^cnFL@kbxhafS~0TPo|fil|5{9j*L8Xe&DOSQ_aCv}2#O6K_yxIth#1 zkKh_BEFKI?2ZuonJtxI|^;46XV?+&VFKniLw~?!C?HMZPM0NsyB#Vucl*xCQ_Dtsj zUOzvcDz+c41hLdgBAy=;J>RNI5u-;qnjLlfJbj7$iL3e(W7`sj8$y+_sf6K-=1FL5 z;)TK!=Ia;Hh>rh&3$692K`7dLzMfGb)G8dW)oW;8}CVtC(b$$*P$zM@gK%@z+R8*kW8FK z9bRPZ)z8Vl>Uh$gI41Y<)`gc-r^;y{L zA)Cl|C(86Ydro0uGtvO6r@kmUK~}NxP;fn{{5@U3+h+XIbc1KobZt}{H2^Uh2p!E_ z_yYoJTPSU;5Y$=ArHK5jmdKh9$5|(S)N&K&Ki1_L@Xsr$)&yU91xzC{`PUs8Cv%pM z(?Wi2{-35emYphYGjZJT)pZ~j3Sj1YiL528eR2K7~he<&^a%Z(5WpA0~|Z z(^SVAA}S`43zX%oR(p7nxl--d0~(WuSZP)wh_s^e(K2m>wjteSVcVmF zO+q8L#ezUv4m%TKuL9et2_3d{;r4dwPpp3w5AQPtR=LBPg0>_#Rni*tQX14}?qYSi zSlO}OI6v`*XOM%NZ`^_)TlrTN;PA9$8_I{-U;lSJZ`0U0`$F0d^P7AZ@I8QvwCb*n z5-8d61(>lv&cruxcVnWAmSCvq+kn;nSoS3J*`gkwK?Xw=^NFHY{saYTkiu7F1e6dT zp!i-ZWsLVwGKv1-)%|ViuG>+O1)30EWOj^|zd5Y#C-{Z~3;rPbbv>Nj{3vWsZ0l5<^}bbEqEd;{L-HK!eJqF$oy zY#$~VehiQve=ev!*%d7OOB$8!4b>B!@*u6pfqQhgt1R5yt+^;nBmT;F1*z2%#_#aj z+9=l<_r6H0pyS;IT}7AwB5Jt!A%k!IH}raTqNbAI4=T2eP*JbWxoE?d+GpjUgHE&n9|0&=u@6N+txLU$IZ?JBE3A>HgV@_ z@M7^Sb$FPnortMpB<+~sg=p!5BJ=0yG@H7f9+w(o((Z@+jGW` zBF8WSbuU3=b6;|mtsU?4v0|?ECB!nWl`97rjMBPu=YcwM3!`VljBlhx+HT%1R*MbJ zeC;fewAA7b87D+Menq5(NAOeIiC1*O;x2`xdkW!Fo%SniDHcY!&T&gLV#hM-&&4xU zJAqthkd1LWQ)i@Wd`6;?Xvgh?BS(q=cu?; z?LHVaL>2k1uy4;J^RctNrG|=3zOc30*S)oJe_46q(WT0{1o*@E~w4j!8=kB3DUztH;vQG0#^IEqY7s_lPt0gsgjwnm1a%Kzj9~ zV!7@+xjNo`vg^K$*=VEN3h3e((8j2%(g8G-gmOtf>hgVhvg^}N(5EM_?Nb+T4aT%B z{5chj+AECj{KB7=sI04koNrKvz$oSyqWgGT<<<0$-Du(h{-_yn67dR^?#jZS;bl8J zF2={=7+X`ddo>$xThz92uluUm^s08+$8<)fxJ<=7rqwcX2 zqwaN38uPcXNs-mch3-`CB*iX7g|V$sVSO;(E`t-BDGFfb3!0dD%IqWzY4<4(IeVgx zsKrFDoBvxAr&aVFN+g+6XE$(F9%!Ngb?kH(8p-%ZhY?a^dX z=#TnY<7}d+#Vn0}xu4taANAKBqYBL_(za?b+E$yFm3xsiHAVwAkHJtVM&1@1oF zdt2Q7xRLDSIj{Ock~3;wib2Ey0`?Jrbr3813bIyaDbayAX-wbgPgjriMw716)6q1Q zo_3X{4+e4hiE!aHWDI%Kbm5!0ywL;@nF=gHzA!X=<3|5DU!hzo45J)B6qSon*$Z3? z!_lxLWD*9+f4Fu6$)e%$FHz7C1r0TeZPAjC#X^VAb5p}uIa{h+NNo-m3nzN^=9hx( zM8CGrxFysOHxrOOu@KQ26J)VY^090s&z>;bmy%hWOqY&eGEuGB`(<;~?tvIameEPL z{uKXxYu!Kt{n@uTqbup~Ksjv1fM#c#ZE-eATD0BdIXtD;yS1ty3&% za1EbySrwx?!NYrUo1#NwgF=G3j0TtarGh?-g-m9BkwroNa@HY1;zYvp%{p-Wc>aE>f%;3|sB%=^67spV zTwfv>SexJJ@qrG5arC0N(pH}qbqcbu^*>-GAX-szF(PNq<~P(hp)|0&m_M4P`Wil4 z?Hny&`a5`@!i+hbSWYCCpN6gPN@RC|4rmt_dq_09uzKh+SUHD4upIzAg5T7u+@Fz`cL!6|G4G;eH*gvy@k4 z53gE(uxdT!_u^y?aRQ;#daNGWb1qs|qu>{xtS5OROGG-$`}`>Lgw!yfNW6r;Re4Tt5Iu zQasRRcZRgPJ8lXEc8Ch`4w3B;WO(%g^_UQE6Mk!lr~u_IILe)^p=rY)W)q+o#kbVT za-gksT^rb=K57)i+omdkcsp&^P)YF4+k}}=Vl%`+PXa7fc&rY&mM~d?46{3t?%P(1 z^0rqp(TNVkrIRQ{aJ6Z`U8IG!9u{3~+rLU>)8qFpEj~#QasO@&N}sQRfce!0ESeUt zpvB!Pec`f)#a2`-!YH4rlvP}(T2)=uB1EpNYOD{j(?w*(UB}pzX$RLt@Oo1= zO2rRN7T6s1IzH+zBSE?#ul4F;x&39-cWX^MWaR1f8NK9FXeO|myWL|x1JmEBa_^SU zloYgx?kHaM(e=dkpiPV4abhI{9`TH_-0qtWdM}+GK32hc2lq`B*38vE@M$+B$EEvs zKHUZ8tueV3KEAkot#|Xb;-+_Cby|~cV6TU+%N5U~WGdfgp7f)he^5V;i|Ic~PgI|b z&Q&dY~rZ`#2a17`B=IQBXg4M^lTD?}=IW=}Nt=6f)%v>&W(DhW5nqZqRV;N6> zT{g&48l8f4VvM=$&uGf>L$2J*tP19tW|EEi_AGCyItW|clNmgBcj4@kU%c9V8Oh7s3ZEx3c@ zZ5g-soC>-A&L0o|m)6OGJHMbG0bFUh;%E)?+biPv%`A9aAA6Vuj~ikSv*2+k_Am<` zNY&gdY8E_hj6KYP$DhX@X2AnREtkYBc)Tk1Fbf{9jy=qR$7^B_v*7XC*uyM%ye{@I z3m&hJJUqrF-7RByuycJ_utbU$}wXQ7cALA#4q?G1I^2Leo3IkNS z%)gf@rqL{Td^Gkj%hsT-{J0Rn=GfCHpY;cQFW;apV5fOyvY1b$Q4mk+ZR4)sVC4~j z4BeZu;hV}#q_U-LU!yNohd&{YVar2J)5{wPN!Lgtb=3e&F=I5SD?B-K8YtufM%pYW zGkhmmOl?NT>O9KHuWf;FJSdI!@$O|DEcKf;ZNyugCD&N4;F91)v{jy8J>8qn-T)JlZ^ z?KaFhs;Mwnyq>$(MmmZU|Hd?3G(NJ#oyq5;i7?1S{BcUSMGQ!3ju+2{)u}T{qS5g5 z1k>nC_JTYkPt`Ae+uU>Z7u*{K`BWK~DVp|{t0H6U?g z6YhLi|002HVf{;jHmv^>Mn_ox3I=NJbs;2ISk=EOGYsorlgVLN)lK?J?~<7d>hG4B zAKm~_DYR9k)81A*#LeyVBiyJq@nc=8hC(g3zPB6O#gYOwyvOk*%k}ZSX-g+S-lo4C zWz8}N@6tg&$Z?A|@XRy$&~iW4vy77CDqXthYph46H&#z2U?Typ6<7qNqRydxQPkblV(RnsQCti~ zcUN~%G%KUn4*|a~ys)Nl>afj~zb)!M6cqrXn|#@4h_ch~wM4FNt_lF(EN6W_6E2^L zD0^rakP?NSYFjSq(QDy7QO}{MM-A3focP}GlNH)KyG-v#z5VBFN1;%xJ_#ZF3L6Hg zs8pI8+P5ML#yn#3UeK*SDi#JZ(LmHYzfu^iZjyEIkhu#382wX2%}|mK#(4}XkEn0* zGYTyoii%XP7!|EPQ!gg#U4MwoxLDXU3qB<>(WaHc=3-%}dTF$o+Ol*llUsR3;@+kA zfl+(xciRJTzF$tZiU}{xtvDx;o*11NoxtlFVRS-tVqfKa22o@>UGF4*l$+Xsj%if( z+3h_P4FS{OGZ%GUJzil9Mx86sR<0}G3QNq3oQLpe!L%4Dw@~C3?Ql=O&GqTY zRW--S23SjcYm>bW0ZvvwpIn^yVh)I|k2V>+6VF-;Z)F|4QDwexO0h7?@EWDe(dd+D z6b5U*T`M*Dy<(wSJ&pQQqUzjAVJxb;&|BCx$wXt(_zlsR4bchi$itmwsLHcSR#hUO zGX3Fb6ZTCWnjO9D(Lj7Oe_jU`{<&z+(ue6DM@4owL_^>#)ngc;= zM?!sNZPKNxfNR5C(NR@3NH~UiNbDvcqpNjHx;CP$NLi_Af3F|L(%$|!0Azjf9 ze`iWmti8}xEHGvf*^HI4QJ2UIyW8MKSJXC{oz0U1BBzi%BN~dMbcJYRp$FV3Ks7OX zFm`>2X-8gAGkIa`;+it^;(aW6VeFdsUIWexV;9eLTC73mg|X|0jB(|)i3zP>X=Up< zxC^Fy3m9xa@f1PfT4>s}yR`eE@D`ZbU3h6uG5Fo}FQRY6X#w)h zc#%h+#o>3?3w)easAtY2Lcc}ecV;3g3<%aJoJKH-NC0b(e0t1>-+8R|(A?}dT<*=p zJ6Mz@W}gYJ3k-^|p|}SJIe5p8XDiMeaa!TpArd`%j!&sq$V_shlugHua}{UErEJ!E z$FzL2K4o(PQp%=dN2lU^gO^U?_T2FcK%c!8A3@rjF_o(6*zqOBd9&j57SEcegxQb! z)@uPTuGU{D@)bTqdVaM6O~(#3{_Nv?oMwxt(57SRqS-Tjgl5GRq3M{q-|V1|(5#;# zG#yi0W`F*RbRVStEqMq$>@O5w=GmMFWgSfbtS8PL2`wQjJ4j`5TsTP1#amR9!jRCzo84< zraP0V$!w6Cl-?w7ASF}NxTd{}yu`2VWnjIEJd^d$QD#0_|2#%pvi=1Oh>WOPlgNa{ z)S*l#$sc0r`6a~iscFDp`a3L~5KBVyr35|) zUEO{=STia{3w0-s%!VsbP6Im^Wtui(&z1I@v$C5suGe|uk4to6LEAAqFgvUFRk}8d z=rJQdFV<^(Sl)#$ekCo1f$3N|#E%>uQP&~f>)BYGcm!M|fx3}*>YXmH_H}u|nJF(Q zVmH4dkj!@GUggy(2W*z|ii(K(+7;;X((j}Lfl9_8v@4m*BPtxK{xS0Sj)~2*VH6&s z4WkURcRI=)5}!^3BW+Hgvk}gdTgNyo($U+Q3es^ zRp_OBY`x4jQLl?i!a1@6+#batGJ%EORX}`m4P- z@uMimf&ig4P1`{}@si+&MPvVqg|69uS6^hn*Qjg7)1ZTJ?b+hNLU)lZsXkFVNP0I- znvDwh%7}Wd2Y&}_Op=rQ&uxdDrj$MmLk_tQg#6YyFTHL zB#gCyt^F?pYml}9CkT5aeC#_RhIlW13w|XNlI6l$Aq_yyLBasnb*zZ7*9<)5%TM{9rXR zP)+q$H}rAnC`xB4d&Gmvasd|JJE1kg%D&ihzbustos)nk!~qwXC9FIV)2++XiBD6v z*B((ftEUDSjH_VbC}*;ennkz@3z#~;kVd9pueM1_kYzt218tWCAzb05Ge%u{0%1Pu z%Wpmf$}q<6+BL6sMO^rKmD$0(GSBgL^3pE$S&s!Hji1gW4$`!*qi(7CKa)p3RsXVT zl&asR8gV&&H|NgglDU>kfqKm9Bu2uV>HyPW;P2@|+$;qNX35E`)`h-9Q6DowexZ82Lh3-ij_1jeddpBJv85c{c0{WpJqlQd~#cL7v^cGtPG^8OGVtE-? zZ>cpndqi+wYjEy};QrR&{1L$et-7E6jIL=?9Aww?_RC4OB;?o~gg>Eo@2_HV@zR z@$1e&ng!dp`5Hu7P9Kitpi5Z@Qibo9rzF##eMI2OXI(UgYaKw7x9mG>og$% zvC($Fql0Qm*d)(jgCoyccgK~00|9SybRv^Pl`Fo(YndkUQCl2=+|>q5janXCbz(G$ zGE<+ij$}zkML?e@HGLJL1lMhSL0v*lOA=Hbs~)U8o?lfl!OS4uo0EzOdn1HnSP4m< z?uX~i?YuFtmAkDL6Nz8WZ%F*CBbE5hDeZ~(Hn!Nlo%D3|H?03S2L+rFKXg z+KdjId#~JDSq4i8Gg6jOLkw}SG%UA;t5aIt!r0dIT9F1eL%Q^u*S%Xry`c%-yDdMF zIxaAGz-Z(LOD8r9|J*vaf^xxF;kNZQH^LKj<7qo6O`edQws;q7t-#@{rw z!RMO7+Pf06rQFb9X!XpX7JGLlZAL+h}9atr^vkxM8Xp8|42rqn~rB= z{|9oU8eccRx}mG~3eX3%wIa*5;=&u)PEXk$x;sR$2-9b4k;rVzSGG6Kz554+zuh@!Ofy zyweBR1&nVon(<5WsAs?t<_oj)%#-FSrbq6^xOyy?$s*QjM*?C*Ygo8G{Y~zy`aTJb zK1#3rt(KP>NlG!_z$_h@YslnrV}8*#M=Rd;`!$p|@(u8v$fq%WFFsHzQN2&^=)x7v z>a^^xE%Eo)i-u}-?c_UcP>m)QT;i{#y2N**NVDQH#*3yJ%Ic`HUZ9E ze#y#xamVi+adzTlJ8A&`pR_kt^49hq7yh!@crCRAM?SUcUp}W;c_u9tly{fB<>EeP zam5Q=@?m*uIvtj`Pn8yaN!sw17i+}n(&W6uwID1{&NsdVj6tQL>?$wfm)_JEP=}%> z!klCkaycfqZCSYB5iwpT4WIo>x58>POALvH5USgcFyE#;D$gNf?zfP^H3TwvtXl>b zQOH2w!Hi&Re*GtujxFH7Erz=g35ErvhicJ1&Se8 z;NTgZ#<%6RLB*?UL0wI?cu)~F&VtGxV-4z}FHYCVQ5QEpna*@*LCGwFG(Q?YwfwA< zy6oF33n!f?=;UP=#0BPWR=XfB--NLKuf!?s3(PE+FWlRZ2V>O?OLl>Ixw-B4o8`Nz z{X~&ni*WSZ;IEsXrEdZvFAs?FJrWT0tc*-4XER#H@~oUwrc%j8 zZH^&kS#XC`K#?RE~%4F(;QJ?QEbu0s}uoay9<+nNnVZmrtTJ6DLE z-->#XIQ1YCkL4CQTEj$HQ6b7tzm5HlC|`L2)dPw3_GcX&{_EDhQ_))KUf8nIP0|hh zLb7X*yT<)WSZ^nF_PVg%;muAn-NKg#G$}W%Z}AB|P@c-cw5^h7 zaIAa!lag;o-HsAR-JTRni2+X%Ji^IO*XE6iSe$q7vGOiWe~R5YvOw~*Plb^6{?eYk zWUVvo-7Ax?VPy6&Y`a&`ILWAe3eoIeBjye3;*F6M9V`@Gw|fn-JuNaW2I-uW4I)9V z_o~O(Gi0+Nf--e!zXGY~H<4@a6y00+ViO~MwCr?SiznoXkzXje;v4`?8DmSSUKke_ z*o=ruWw~o|lX5|lh-kZye-k7^PWpW&>_7@s?aeoaQ ztG}Xtj|=@C7y4sd7z7vk9WIzeb8X&eam9IWI#%ARxG=aD7j(kCBkFg!FbFR6J6u2* zw(DwBq{uh^h2g9HUkzh)DjMW=Rc zB7sgBNq}k?i3qC?*OF^(wLl0}D`fa&_QHau89wQ?!zZn3xzPv5homJPqd2=;+1$$H z8`$mhV21{_qb!;0BK8PGc{11KsBg@tzB?j4oKaxHHLd?a^YVYer^d82imH{#aLZ%cjTPXdrRi8 z1Dumq3y+f@rJ@GQ=Q#yr%>_3zoprG@Mjm4MZ%dufZD>l@-Oe)NvZ;^zd2E{5ND~@2 z;6f|Teq_wn2Fxk)UupceP_o$gH)s5(3~R&2zsp+Jx@4@E2><0G{9H!mPv}In*Iz8d zcf7U5`X#R8CHOj9B70I;$t;Q(E`mr+II^IPgYdFiiK>Cl02thyf+v`t3?ZP1IFj)2gu zjsK(BH?B+772A3_c5eczlIwckr6YAA0XExHuD!+7rhr{GOqjAk#mE4(($5RXa1$E2El1+@q{bT|=>u!gwuFuI` zkwFd_&1~29iyt|0S;C2DQjWukmiF#MMq^{l4I1)Z*U;1Vi<|M+ZDrp!CeexqrQpzc zV+Th|ou^z4k()YPZ$%7Y^)v)||@vn({wJh`Qy$OV` zVuo5}*P7;9-CF(l17SveoB&s({RrW!rocW%ultw4%< zZ_NZLWVNA1iqFJqqLn5m-Rzi}6FIBD-29hJ4ATyOV{}l1!Cor8>XPI{XOOfa8CLSw z{oC%H#J^SCE6WHvwD;5zW|CKu#o$f0Zxc-aNNXpx@sr3`f5SIEe?wwfg_o8~{FZae zI&(K1P^o2Y9h6JUTK5;1rM*>J7K6WOSvo`I>1A!G4=ig7v~T#v_jDwThd+OASz8Qj zY3OLm@VAp>q-_8m#&hTSij|j(%#U)Y&0FJ;lnW6b!(8oTQ2h-qtEDR?_D(Gc#OZ9x z&IL|QE$nChaRP1&u{qPiR%cJ%JpU)nQU^${$8}FuZgu^}ce4I~;DwP#HRHI@#T@|I z;3j8D*-w!X)a6Po>NsKp#qCs(ZfucJY;2WLd4;M4+26;?!R4a+X)je~{JEmaC4b&aH7hT)I_}r%m~C}Dyv1Q+%@%i1S5x>?Val}j z0M{sO^yx*eXkT{iY(lmMb+u&ek!lr}SaL#TVsb)j*b#I4m^yWKfp75Zu^%oXtW#An ztW$cd(^h46+?Vq(yFy2Av#WWGPyTmck?iiC-zO1lYxYUfaIwXF8b(U+CR3T(?^6#h zSKsy!j{v`E%cQcL70qPl+rsP|tE$PDLUK={tZ=R&L;DVH>%qg;x;r5+8yWFl!ij;U zJrKLsZYp>exasbO&C{m58Lct9XKcEHDn!2aMt(S${J3&{u7aLGeqn~e=4J11!mVf7 zFe>bG>uJ&Yse(}_XU+0cPsZ)0l*SZcAc_n(LT8+Z3^z0@e<55-HUOxV=DZbOPjk$= zN^{I9nj`kozmNAf)z>(agWsa%e8H)nDy zZzBWSh1WE4a!^+k)?6xc@lAx)>ckA{$|O^JCU%=(!s*Wk#l?p5ydNQKU2=u8j9F)F zcgE=$>gapRbPt<943uyWn;!rRM5ry$RW4(|~yy|Yk1lO#~nQsXRTN)@C`%iX^S=gg6Yk3cdZC6ysZ}jF&P~OV{fpST`ww;`au0}Q{mH~b z@qe#isP7=QWv{9gr-xnJ1a&!UOH^HVE5DbLeC?AQe<~F#?~zaC-TZQX+Bp%~8;oN* za4pz)U_+TW`Y#x3yF5t8r2luUqyOq4Pydy{ap=E_YSMpm#Pr`BG5t43O#jUh(|A&1TU3lo}zdRiMr>_MVjjM5XH523eXiKe11>_p)829NBoy?mWzLPVT-_ulEBs!>{ zCfJau|CPF?)R41?-fd6}tv8GLUY+%JXh2nDVSzp2Mn&yepu%{jl%Kr{)bW1H_>pF$ zuJHf^Y{SCF76;UYJ38qWSZHIKC@3|(k;0R_o1-~GyMDQC6TzLK@N4l35^x0i*(#`Q z;R)hkOvK?4PnWfD6+15;q-+?XGc%92amapp@vPI(2n3G%Q%IK0a+&rP7%Xk#{cG^N z)DXre$CJEY7t}SZYtNy?t-ahMl(XaB+1_f}l)~G3i6Ih`sXUh`+h0jX$6nSRoF#D) zYHEr0!`|hdD9jdjUPb~pp0d^)9l5%iA*hRRl;*ZQ(4|J8S$RDp!@06Xe-5)L0JsF>wa^pi_-BsY z8ylsP-X1j0#~;q1dD*W(NOwRRQ5;DwM)5O2(xRLEFa^0=FgO;eq2b*aJLyfQe&oiF zSRjofV}XpYkC;1W*idsUkoSLpa>~p#%uLnJA*;Z(T0@PN>or7j_?N3|Qgr0HcZTO1 zt3faOlV?5v`Eqg$+Gg~*F7muyT zpP%S`g{zx5g3F$f*p?emxj|j*hJW?**Jq}huYbnxdXy5UKG@Z9Xkb|r{^*HI=V1gUZ&f=yiSd6k-?Olz z)RcG?%Qx7F#5mt~@MBg^{3qr=;r<-xpwa<_vB&L=(4Q=ki?X z*(Nv~l6V#2`}zJxCT^I+1PXkKw_qX_Obqg&&XTx-_$TB4F#H8qjZgBnAM)wG8d#dd zoA7%Iah{5){GWq)3FaI5_F&KQy_)bZV%|plzs7t6Ca9Zu0e02vaz53Um44!HF&{Xty-A3A*__#$n@g+VG z#2$Y^-gq?!lt1$QBz7G3q2zx#DNAal)&f_G$PPqE;%lILCNMtb84*h&@=2N-1 zN^d9j>KJcI8a zvEPTd2QUTiC$YZ_|4aCCd}<4ZR02jgaU)^Spv0|w(#hO{-(Ji=Bi+aGgP%>j81uE5 zpWyod{yX?C;1llNNZ4h>kFY-vyKwy^zQ+^(C-_SbL~XPm^Hls_%y$9tQkd7_*G(AX z*y^V87qCB_@0)yA@(mFFb4=l*a9#Q@uOzMF^lkf6YXA@zlZ;0@P7;D zGT+bngr^~4pX4hL_ASh3kxqD`_zONH@ z7w(r}Zo~b1*fmBpKCZwG%ba*Q_RnL!5c8>osjPn_9!g({Z{Yqb?DxYiTy4jG2>Xxm zm#jhbMR7$pgo{7r+e-M)FwyHtT+1gG6p9|!V`6K*MqDq|3_eJu4I;O_vjeIXAj>f0xo5uL(@Vi}kV;;t> z^izDozd-)j-+_4+;g7)YF_?eD_iFsKfACboHP$r#e~6#x@)>-h$3@Ix{9l2ov3fc7 zFXDeD_J6n~AKoB6)VcMa|* zV7`z~^yNEzA0l1?_g3tC`9${w!w{d~_$=-|z7O#soKC!zIQ`h4i}}x(!m9)LUy7-G z<^MG7r(vQaop>9c=!oXG=V4ble@eU;;BLoE^VRWFnDF94{Doid$Nx3he}@0dvA-4j zhxmj88qYcW{}J~z-}U&Z|5eUm!j%5+ao04sfOYO!F z$Tl=U+g86<%a3VBn$EA4;jVLAx(s{YZkG+CQb}IqvWa~UI$xSvna95LEDKJpH$^w{ zTGOEE|3~=lZZwpl4qZ&a%`?TOD$j?HM6LwMNLBs|*0u3`MXCHq>~yj5A~}i;8dC;y z1v025SQ#B$$v2<}DXtH8fiH9hhb0{`mg$F<~&{Dxr<0csusHWdneGY(Zp)J^*=2jL# z687yb-e7yn);-hTVOc#T9W@WOzvZBv~2llK7xtN%rl&CLd6b zYq&jhx;xCww5O9-r&Cwo8K8DKTI3Eqow*Xd`w;Pa+mfYgq$;?%kRB+6x$*q)i0(`4aNNI&j`u2CuwkbUt_9-vw0GM0WE+GAE2DdEgE+Y34^-E zK#OzFS(tI8rO$X$KBo42(mL1Qc#E}pCC%%E4Lnzn}2)hU82ImIm<_ssb zStI%&Ucul<+FsuLV1?N)3>e(rmL8ZNFh54kX27!cXep}S08}z&<0^?(6SHJo z4V`L|)5=UHB!jp++yPs@dR%OIUyLn%Qoj&Xl`l|)KTkLQ-Rd7@$LDZkyliTI$z9iUA?TRY~%C8g&TjFvsi( z+$agph;z&}+h%~!gP8aXJ*ilgjjssx?&0zxq`k_?Z+qfne9a{^gBNRNep9o1S&1EkI zvI~8_BUWH&q4RS_slB1D(LAmf%GOR#hiHBMcy6CaE+?bDXoqE zjXWQBGgqS@7&oX3S-ODQQhnGn?{jH;=uv$)kE68U0_D^P(5G$mr>7`3Bp4fN>zjT3>{Yqc9rx{%{ z5AzM`sRZh_Mh0L>jz%Tc5fP&jYgjgLLBwci`pmWYt|KotY#g0gLsN$49W^mnpS=dw zp{aA$X8G%bTCF(fic_4JF*NeEJ`%dMm2zz-n)_kVj>=a=mmG7N9^+>1*1Vcv9YJE7 zjpwNAnp8~)QWrG|jR%f%5!NNS)J4|bLH(JuFz-zwR|rRc&UCHOT%1Vu^2WE>*NpOH zzaQQJm>jrs!}_rCY;s^5(D#kXERFVaqc zdj;7GXYd?PH@A7t2&+~a{pM)Pgp>J9z8aVt!&i^=cpkww< z;f_Zg1-nRdzH@K4P~pAvcVmFXucF4B)}J(k=No2^QBjfR9a4?>0ph%DL2L`?ym~|n zYP-V0^I>4Bc|nO4e}c=Gv)(>`F>6j1&*LZ-E6ma(fLNd2ypEfmVW14=xKh9{{cnZo z8yHe@xq8O!VnZrd`yc~XoTZ$o#JI7gUt7{oKZK5REv07nD#Z;g=m{{R{#+d57h5AX z=hzE^`f~{1;q6 z)Frv8BX>=mC1G7_6ManX5sQWzw+U<X{U$7)>qK_=g` z9&8>i2X)Mx#hY*UgSW)ERoyU}nXDha3MkDtQAp0ddDl8ILUC2KipXWp`W@-Q5vz_4 zvblcbTC|55^VBfmuO}2op)Z;3XB>T0Y;mKauJmJ%T07=Ag6D3LbE7UZmWhW|+(7Zn ztS*R0<0{v8`o}mkW-oIXbjL|FdxK7wIUu$i7YO9bmf5km!nMO#GPVQERv%>ydvtyy zpfbUzUtto|>r$nXbIoJ{!+6c zaEALDtQn5Ta|Zfxj1X3$#|Sy`m?65ZX=j;1VZFf<=kxO&+?lMdndiph6fXfKjmOLt zbeY-24xiI8dP|H5w*c(%tjS2%hA2Iy2RKLar|X*S2(%IQPjWveoS&@HFMX{{DH5Ay z8w&u=&3{*%_c>Y&EIpp^V&(htxPQ}wH}1?wdpD`XL+LF2k%{9c_1n|a_%0O<{`DE#}RF6VBzZonB5&n7(#IA;(7M8!5*TNcrPbw%&*kMjjN2=9rZ&x4S=YM+G6sAewsLops>UG&_dCb##w+AXHMGDBI@1j? zeL>|1v~@9F_ec*RZ8TxEX^RKgQ2PLl5;oZWr(0Ls8=@m2FvcG^<25pZ3MvlacxGuo zE<`r_FdB;rv82Twlx?q~XBroZFv7%HfGs&3*FzzROOBDjYU8ynOguUs z6du`KY3he$kuMA@xb!~GjoJB)^yg3%? z@1>E(s=j~Vf2D`)n$MQEpimPTXQp76$6e^sUceZ*&dAfkgK2-CNaV_00cJ$X`ixsZvmSl#^_B=8DqBNvIfaw$ubuPIT(+RAF;4G zf`79r`RK>Mk5~X5#bek-KL&p2>UYg^5pN8xX1)eL91fHkHUS!T=xIJrOOmFa`w3_X zXF0`&3@tyN-*W!S9ZWP_9JTPk$0RPhDJ(5qVrJjMo|N4E3(qq5z`{$-99(#dnVS~= z-ptJlKQMD>Av34=<(yBrETU5$Ue=f{k1lHhEMD8_i5NGzX&p{3bcCb392#YZU2FMKl-c*eJ4tjr=YC z41}c31_p)(O5V{oFj(#yie3E!o65uG;n+DaFi`F)clG(WgG0Coj@_GZ4=+=e{lvbT zhswjwSG9?Ko1WTd7}ks%hm>=~H(wXT@;we(R<%aO@@^_t?gV(Vr(5is($4>?=9Q9f zR!hJa55F>lvT$ng8nI1(seBOV$*jK`vZ;Gh--3f%4W~ea_*O%OCmR+aj{Qc(rjFXH z-ixWfW2UXYf!O5vP~~Z}RMP4?F}!dsUhcv^^KqgQwm)CJS5X%C0x(PHxu=!=e7GWb)QY$@EsaQp-( zC;?|6l8G^({3PSgPJ1%?%DKf~fW2%mS6&M`hW6ln`(Zl>Ut>JvZ_E1kio?Xfu+(^T zmg2biyzW=eC(wBeopFeQ#f@kPvgBO+Zx7Dv$z~lO#C2x}Gl}m07#5d@>U3ltZ}^q+ zVD^0{SfwY3-)n!Vcw z;eVTc3+WsItSR!1)nv|d3!V(ulLg6NVdvnbC9@PRD_tNdzskNi11-wmB``f{+>uJt$lXWEQangLH%qd7r(^DW0qG}Rr@4eSN64Q$!M$-NyW6fP1UW2i|4p8qX+`eQ9!rf@iOQdsy*mQl$5f2 z>2Cz9Ico1BS#?7X7fJNDhRG3!aZ9bG%Y;{5Qkvs6dG4#V$eE1y=qTs2b2+=x-6TQw z_<-(6KUo3{_^e9NkH=z8wg_t|shX1VKvTjh4SN0}ixn`wEtAb93m0lo49 zNauK0P&o|=7qHTF2Y0b7aNp|dn(BiOD?c-ou8^_~?Mu)wfd(|b@K~egu zOW+5NF~4l44}Kf-RGiOmI8SZz;QS`@RGi1JHc!25_-&BsQVD*!w1~1=ep%hR@Ia=B zN+hT7nD!Gt@-(_je?iF|2KbN=!rT8&_QkV-zwu$SK3dk#$m-4n@TR&P!?(lmy5#>L zciND-@o}>^J|QF3_>_!d6E;zg3j3SyKg~^n4Yoys&bQV#vb@ipgW7_Y<>o6(372J5#lSF!fw|;PfnJJLd*F zkOlIc*vVY*hy0+kmo9c~s6K{khpmEHS6zb(wR}P5fE+Py7JwL-+39E1DVZx5a5;eG(JKm zVd+BMwM5>&)qTeuSQ&-rFU#qQtVmhGQ!&yp&mTXk`UY&Mpxb7#NKK7d0Y#65-; z$Z@WOO&KiYyqVX1yIkDJJRk@wj}$rtbs-ry8?JCG z^ZpmwCGdqe-beQqN7~z%++`g{t|ENXL-nc6JWA(!@zv~o@}~SfHZ;Q1rLLvh9W<_I z5ZG!^k8yXiUHNeQK_7*ue~MwSZoEnJ`BxqnV?#FNd#tykp3^`7bGEWqJ9@)r*URt6`*(*5 zmOE|02vgy$_ptNze$@lgR^B|B4+r;~ZEF4K`N03e=rOU9AenPu%+V_!6v8qa$z(5v zOX&Q&DDtQ>y~$)>MrY|V>TpD(5NS1%e{gmuHle|ey@0l4T?y*5Xm8q(9zgpu6 zv^et?m=9m6mHg}rf2VpkG%h3XEvnWnu4InE<#7SdmGOUpv;|H{h)tE9ZEzZTA!d$#EHhT)M~b;2vC}l<&O9px*5l z_0Snx_xCh}zwYekFq4twf;w2Lz@k4>8l>U0#5jkxtRKC%TT_>Gmc^a53loooS-*v} z#kSe|V$F=RP85&sdRYpBV&ipS$QHmB#yMox7OifM)FsRRJ(C2NlhSQ5bk_d2?m=rh znBlW=H0M2H=XJvQhT_IvrWM61T&5RAjJYrvT?rsuEghVpY1gcgOtc33(xqnNt?$F? zRcZ_}cxw5~HDtgQsq(m78@OLv$efVj#Aea^ySke{*W_6nSM7+tj_GImcIqLEBod&6 zG>sF;gc99y@Q27Ef#^c#s1hNcWE+wKwDCzIfH)%|O)10~2{?`f(hTj9+69gK$^~2R zkKBxolz%Bvyqp!}<0-B3M=WFKhvB#FUIvK`bqCE|M7WCxcM(CSKgE#i$o^eK*jJ8x z{wQ4e{KZ7Dn_==O&X5%w-&6-AZ*BZgX6n|)k7TABKbFC!^H0o7H-2hn*!WkOJ&kW; zAdku={*nrFA4p_R4zVUoS|{*uN8V&dEE4l|6C8y}6C8CUO>k65CEXH`rx}vgN7HRd zCppR>IdWb+FpgXXlogD6gxe%XYTZ6+j{GUX?nI)D#~1k?K`UHAcTCe2&*Gc?2Y#Zg zP4hc-4HYjM<#&D-OEPCtB$jR_M$((-CPIqxPJDzQ)meg zSE=@lZ4I*Jje8p3S6EBjZ^_-~;@)6!ckSWgjjU_GO#k_-ap$bO6OV&xKcLdc5QHVO)Bi2BygO8DCsqq$E&hK5vD8p4h-J<-h&AYj8e)2d=?$Z{ zDCZ^(Uc*8FKKQTf34Iwr%(xyfs#~W7c8|o1;-#$rhhlNqnNJbOiNTWGUf4e3Y$05u< z<7Y?+{{MyzN0~9#v@LIq(r~;wwG?6;ZQoxjc87~k4UeHaWo{9x3Xb-Zeb#dy_BXU3S- zLJA9fCL5esv`Elvmsquqm~O`+0uyEDtFp@zJALfPSdyndjju_q@T%vSJtxOGE($T` z$SEzv%#ofO+qYNy1A3c`*T;IMKh1?&`8_WLb z>Ys|sQPQtnp^a9dwmtbyYQ(bV^jiq3>7#5Dt)=SwHXjwvN;bEsy5`rZ>N@bahu$Wr~Ryev1Wp!77&Xl|7rGomTGZa zRmGub)b5Kx7^`w*bQWo-F{0C*{^Mqx7F5i)qR#9GVZ%GK3r#M`k73r1G)TIC zf7CwBbFx*iwtqi98I{6i=jwDRx}4hmH19KrjQB=& zt}9>;+)sJ>1B}%Iecmn}cRHmxe>&A2R31d?tqZSYLGu5w_a^W)UETli$(?gE$mAvw znJVGRBsUicLPCt81c^pSGZK-K$W20Ai4ZCgv#6+{R8^^=N}JHuJhZB+v{cPiMa@-3 zDergfbI#2X+CIPM`Tsue|MR}jPS)M)tiAT$Yp*@;v(Mhb$DoRmKPgJND1}R)mCTiW z-)V{fFN;T}??vA5l?U~?$I<8FJYOMwtS7`B5W6fv>TJ9pVU3YeVrSirR?BF;=P_V4 zioGvdhPMDs(NC=c900ULul5e085map`XGkBfQU@|@CszTdaz6rphnP?On*kfXqVqP z#FJ>3kgK>`NbpEKwdjQ^KR%tui!;I;6?1XpWXS`BhTghSidRT$nYW#g1r%WZ4I~QJ z>;bL+h?Z@tk$IFn0yUyBTmK-2CK+Bhi-&Y+h-eT>yCGsI#Pk;-eMuvAR~C814#HU~ z|BYnx{+>@YeXqt+End8d_m3pFSGo$H*d}As@3Uzi1*xA&YfF+!<&9QL?nWzDl)(`$ z|B0x7nM3r^9FtW&*V`?9qz}r@)6prTO8!8UxB-d9{3b2l{JToRjhhtIU+Idz!ejAk z=6XA%BYJ#ZmB`25gpa-H|6=U)Q6G!l+H#tn5V;2*`CI6C{2h2K7KuWSC2ES3KCGlM1)bUZ9qV(6>TQREI>pwSuR@Y?fRoMeN>7l2jdzg%>aA=8 zI|yvlJE-TDJ_S)T*Qlc7Kms8XQw{GHg!`rf6-_jQZR!0PJI**rp=lDfo#)~Q)L6%3 zUMQ=?F*Q$8v+Uz>{>=qzm{wzCMBzCq ztAjCrfoEC_Xk@tRsKk5)vy)bEa#njc!Ux78tD-tsYl-2Sqk?8R3Ih`DtVXzw>SeA7 z0!7E!F3^|0$EQ&iWp2|g8)R65!vPI?V*G;wPu zgm%SQ>B?oU&em?uwt;>;4U3OrrH5VBa>epo!!0+;WoB&R1c%=Kg}5x zBrWE%5u-4a6l7Cj6Ifq7BD?IcJxHDCY@@->A)0SHszdQnbD+#oja@XDIod#CrcZx5 zoz>7ujo-mGjw+gOI@-4i3G~Hr?f!_2B^rsvKAmcVE6O`hs0K3>jzApk!@d>s#@=3w zohge!FrdMYh2_2l86d^;Zji<22 zH(1;L0F))H0IM{esxbI-v_pI7YNR7p9?`tWmYsisSLu#2Z)bf1HR0x$C@ZlAQ?B!N z_I7r0Q7Y`w)({mJo8njBA8c9`Mnv}Z%KS@W2NvkA@_rPe#E!w>MxeJDYT2=-<(Gs7MG6?vZ6tBN*#Zie5n`WDD}n<@&SvMFNiuA4v3~DFN1Y{i5OR)i^}_PNF#ge z{5>Mc`%gqKlSHV*Ey|@n6o)Uxp|)4PI1VHZarEGYGDL}SStSeU3JgGcjaa41?;w&8 zSG@$IBvh>4<6~6X5hvGqEJOU5M=IV{>PkJyX6F#lHA2NKBgZqfz_b}b__g9xt z4&d5S{wp4;*D`k=rvfMQZp1%OO|o!Ni-eAqe9~3ew!&4|d{B(6lk@j^u!cg1OHpY@ zvQUO;GcJYgDk5%#Py{+04#hLFHc#+|zKTpL02?FtO((Euze*fE!w^pUS>grU1bYC0 z__39Q8RE&4;GqJJ@eQ{VKw%L-$`dohpUR^wd>;WP{^bHrJfb1IOn4wXTEL0_JU|Q| zb9rWnM?CY0a5tXJ_TS6_J`h0i&|O1hh-VzbcsxSDDf}Y<`X-Y2X-^Ls;vc~<9@h&v z@qZwp6CW9}D;UP(Jq4WjZv)~06h4Lw%n(26n+)MD0QwG;@QVOZ{y^Ylh+e=j9&at+ z6#nM`QGPoKPo@O-6L8{xPePZWAVc<0hVgh)0jKb50F*XLFQtPF z@lRkFk4FkP@qZ5x%NveGV21cHps?UU0#5vO0!}=%uZj%eGZ@C>eFU8N9{@!8 zlMMNF0*Lxw30%~FGvH*1C!b+F9wy)v{$7Bnf7-<5PuTGc)W>#6Mr>8)PIbGXS@V&FW|)gEr4`EVLJoJQ1~Mm#^XXW z!s^!+30+#>r%ULu0#4!o1`y@PpoSR=e~<*%0pAHAIvG*_M*fk}izIkk0jKZ}0Yv@N z{x~ue&TxkDcyj?K{&f<%v^{xULhml&zYbiKpZt@d@NupHGlY8yIJqwYi2BbE=)_Yh z!8-{!@t+2W`uC9VjF#Xb0#5v&O6asQN`}Ip#V{W4E8xWc7?28JWd}Vy8R93Mks;g> zAeR4f;G#Uz_J0iMWQgCuFgCyCb^{mnBP|bU0uS-~O8DQF&;@Z=n3E**&Jz9~fs5fw z^J}n#-(A8#54c!lqckBjAy_&=7=rRlAb(0dCw@&67G<(HPXS0wzD?>hk$ zFBwt)qMnI9mbvge;Q~(K9|nl}m$v^|68;tv{tXhkRG-r%^d1uao4`f+DLyhJPYT0$ zTx=)FeHlR1e};r-q6Ci;aN<7;5cMzSBZZ$U@DScgz=?mmgf30*Yze)eg#QWfQ~*n> z(BM*-lqNESI{-*#!c72C9x+`+&jXMlJd|O4ecT0{!lLk{?SCqs$q>H}AuuHW3Wo7? z0cAX85_+_N6aNK(7`{rNQ<#Yo+)coVe=a~QKVms2{&4~i;SmB({NDh?^5ZDbiD!fa z*9$oDZ<5f7j||xr4CC>h0#5vQ0HXZT_Mh}khWxq!#P;VRa8Z7--Vsj$fDGZS8OH1L z3*e&s()KV@;30lL3I7@iT`JEM3B9X?|0-}%ehP~W*+Ut|<4pye(z^&iX`}K$=^#V= z6Bx$hkpfQqCjnx4qjrD{@xR6}9uE?5;@>Kv+e+{m61|buIEB9tAnIS*9;Qq9Uy|^zlF(%me6j@ZBH_OTT$G>HVLX#O zNdgbyO$40eSpX3AA0yC-XS@V&FW|)g9e{K}VLJoJ5dTPq@pyoM6aPmNy0pGem(XJ+ z{P%#1@=M$QK@xr)@SOmPmyD=?Bmcv+r!}!{^kB=pV_{)@oH@TK`RSi$tNS+}K<8coGC;o*1 zQU78%#BUaO2=5@^#D4-H>YwyLhIn!q#^ZqkPW-hJx-`925_)e5|9#-1{L=FFiiF=4 z_)Y-DOGebcsAr;&WiC8VxPX&9Ujsz_OWXe}34aR-|3(R2s?TW>dJhTzE#RX36dxIq zCxu}=F1C~8{uV&ge};r-q6Ci;aN<7)5cMzSBZZ$U@DScgz=?l{gx*Mk&z9i*1f2Mv z0!V(+J+-%_cZTDE^h`LldqYIJ1Fuh_6Hq(L_|bS#9U+|BXR7~<9$g>495fo2Gdc!0 zqzA%%0W@A@bRRywgp+(Uj$w2pl*R;vPXg=|aI4h%@DZd%{z($~sr|RekI4X)2MUMs z*CIbU4^jR!&@J+()`w5+vqgR+MwH(Gx<&rbdikmSvB;0Xs3`v~(02k@x>EUXe<^Hw zh8RpP%2!H1^_f(UC@jiP$_uK8R41rBcmtXN0s&MXIsjq-ly?~b6QCTh60iqw5kP&& z|HKfx6iClfkmFejlolyax}<NCQj) z>;hO>0S8zi5Gw>?g+Q#JNGmAO3VNqAL#>eSRz3jak5x1vm3z)02#YMDJfcjZTw)%H z`9yM3UWxf7=9!pply?w;0i}h2-XDtNF(1lt;S21a@uE(D7g&Gf6#<$erGbN)$YCZ-bp>wKPx zLM&nXN%1i`j_YMd=r+Yk`N{Ccj?k6hO?3(jy(vyTU_7K#87uElFYb(n@QRXf{K!ls zdP%!_v`anOi%_3V*%*Dq5~_D%$t-C@4~mlRWGVGHL0&~)x#P|?dQYoQBcZ%x=H7T_ z`?nbaLR%u_%bT=v$lr(;%K0;`um^f1f*g;H)65Y}Bvim;s1F4Sj9(GsMf{kW3XF^a zjM2mhyBpb*A4+Zw(uVSdvzEuvIioRf5zwv-olev+prr=<=*QzRiLPv=xb^vX!c8WD zMwyvdcu8btmPq}pNR!%>h~L~Q@X5>+pgMN~aCW+ZD(nlH&QyZOk_hr_`UR{doe6DR z63JWmE{L8w@m3Tph|T1t^CnI}ZXE({4|%W{Zy*NnmUPWO6f|XmV%3$vpuAGw0( z;Co`!2EpC)NrLK8%rLN;6Y#G7%3QBH0()K;{>r)1VRYWbTgErVsMET3tKU=j6 zt7K{&+d2n}Hnyu(tSaK^Gxjtqo1M#{Zo+QLq3yEnnjl?%yH~k9HNUBG1VrNH!Wq13 zc9;h~g2LuLsx~TJJ&_$NtIqudDQk`|zNxh2p2kB7E7}m1+8FAWPg0qFwq%%FgFDCy zTOs(2^$|-gJ+f>9Z*;l2yjW3janJe991*D+^3!rj{fad%s9w;?eq4F9HV1_(vC3i)F64 zU7>4gWAqI1fDG>=9X~LAu_{3tqIMt`jg3%k1(Ygz?krGk0)3pU^s|8p3@S6Vv8-~d z8nf~X_c>JPPMo!OvU;Lxj-dsA{yaWa<*VAr5^9H}^6^c$eh(;8jW5qRKBl%>v7J(iiN^>R%NiROJ{ zXQ2K)c;TNkOl4Lz9Lwg z1DGqd2Dw+M82hu9o^KiOfeESGTE|)onYEdO<6BnNgjv_;pt`Y9g;rhG*jA&9yo?q> z9`q8Q44IkQ;ONiTEWxA^HVL#r*ELC z)5s@z0Y=2QGK9t4oVEYBjGDESIu&c&axYLaRQfTnnq!kOtLl_WnVI@re>aFZ7vZ9BZMqqHn z6=-zL=14>mI$Vr>b`ezJKZbr?6Gu!U8@r8hczc)zUx!)`u6DL&{^vPs<^JsAcWgw( z$qR`|i6!`sO`#6*0DU>7M2nA7nGn1yqY2x;OH&bPRCjzW=4gWv6Wi*o2~_bX4v3=6 z3%VtuQmF>>Qi)EkiS^h#x5N=p4b!9I1%4cD@Yym>UDAclBy|Mli(cnBs{)6JN~HbU z&?HXQ5R}sy+tm4lXhK@aR8kF`FqtaNsqJ&9%^2@CxCK3Qh2I z{=30ol$&#ZTW;Qjl588}d<9)e4HW>UwGt`?I=jF~m9<;ayr7ms;qW&T3+=&HGiFD% zHBzxmZpOt=XquM~QM6co zLctWKqe{0#C;|BDkk9(YLe`5JKe&W4UCu;v3!6g+`%!5V2t(`wZRINK+^=zs3++9& zc5QWAgNt5SX?Ly0xmr~0U7wK>+r|+aCDl<|y-cohWxho(bOslzD*mjlP)6D?eL31- zgKR@5Ti(eQ+ss+Ym_qScHq^?B5uZvygL94w$yUrcs-KHC+%++439nM-#Wm4UH3FX> zEOoSlf|%gKeFzdMNp81D4;1_7gt6y^u^0SSW0$nPlp1PB96&||T3?1IG&!uz$%B0! zWrwv8u8Hi5P)wIxZ3CTE8Z|az51yCknm)qchQH*HZ%8ho)U=baQZNr&!WBV!dVutj znu0PTR(twvLO%(Sj^K-o+^~n;ok{P9w1``W$(n0Qs#fNj;lQa})3tKw+rdf~dPU`$ zL4y8+5!Ww78`S~rdOgruh7>RbW$P`XjsESqbsCVKGY!KR!)zE1t&#jE>m<)b{68d6 z+DSHAqaowq=)`H%)+!vAp|F+P$?UC!6;dnQ45m;j(bB8bFdD&F3r5?(*fcP<|6uI? z!Px(YrqO?Bm}Z=u@%?~{OJf*zD;!;PAsDv?#=U{TeQIT(mvA$3}rnW$=yR^26_K8gp>|tZL$o8aQNtMI&f%5_A0il2hKr|o@kP4u7 zwG6NvuoG||AT13PwUD!jEXs4&LLLFkvV4oPJ3pWiI;|Yg3KAUT_|h~QZ^16C>Fu8F0DCzj2`uV>jT z{NlpQ*-zrmPUDWEjP^usN1wfiK1y;AHX3% z5MUkPHNbU1Q@|3yP{3(GB;ZrP1i)i}3@{nc1+W|N65wq>I^ahDdKGRSU;yAKAPn#! zARq86Kns`-hy@%31OV0oMgo2TGy%K`NCNx-Xb;#17!UXZpaQ%O=nkMMX>-84fZ>3j z0Xo1NfI)!cfVO~-0Y!k{0rr4dfWCmkfDph2z-YitfEQpH;8nm`KqtU64`;0ss*NCR8|I0EJZ`UAcJ7yz39V*qym)__VtFTfXomVh;YY`|53J75uDFyJJh z9bhY<81N9F1WW~V1MCC%16Bcs0WJX=0~P=h0N(-H06qc~0`39q05btE1HJ+T1J(mZ z0d4?10ZReNfHQ!OfX@IWfIk7wNP)AJHSQh+z#a&DAnaqXkHI#=Hp1QvdoyekY!mFe zu=Ch=fJ)O`xPhKdm8K>uzSEh0Q&&!7O-2uUJZLS>@3(> zurI^D4BHj9E9`}^7s7r8_A9VYz&-&x9CkSDTG+L)$HE>9`#$XZup7Z{1ba5@*|7V; z?g#s8*k8kL1-ljOjj%Vu&V`)|`xfk5u)Se>!+s0)Td-4Lr@%f3`yA{j*io=|z}^9S zBJ7E>^mBfp_t`@;wWAKCn`9E2Z8~Y@DfCX7e7?49sE5s_Bt&QeUVmrG{PN zya10brPLqlN~!5DrS_cn`35j*m+9TbYv{j!q`ru5d6w~4D&Y(chfE%|iRcUlW$99Q z2~#r*Z(nSc8oXMGxQ8%Qas|E#c96|Y#JyQKN8tbKk2tXyw}g2+M9MMe#haN13C29t z-!}LcRp}Ba>{YFrw{7sYs1D1%xYRIRl^QU}=MGlP%ZSD2gT}x}yO!QNNoL-FXBrvs z7+cAu{Gxt+m{6W@GV)4r$$U_=ICdQtk*z3s zmpv*ymYLTA z;nPMW-a#zCc)^Hvg=8X$aT6x9>DEiO94_3JX^jPUQdgj}j8Sm8>?o|w@+V}mH=O!v zh$!dZf-@-LB6l7>7gtHBPy^JsRr)ozpJ!t(; z$@P)5{VihoutM=6rMKUYJo>klha4r@oA7$WqBH-*tIRbdT^*G2LY3`<%Jd_kC&3F- zT(E2Ycc5$34e$BZ-4K z+&VrwHjj2fQM-irbXspMD`7&6Y8@^k7NVnWRO78hq(dx`s&#X{y^RiP*SYKpVxvm! zHrERrGwV6{Jhqdu%Y&U&PAcoy^oUAZvI%KXX)xGvpW7s*iE$vGMzzk3kB>R&=2FlY zHgZXcBWPXPQv69};-$Y>QPJAsWi}$-Xo*+|+AGD&Xp3_rmm;f5Ho_C4!`Z*M`N~55 zfTy~pxS^YUM#s(h{Sr!U9)_G+);ChEbu;!A^3erkY;aMhTXMmbA55^K#_vm!)NZ2= zk}M-hK149Mz8Js!=!7)}kUz>2l9G4W43;3=Bh7B7rX>zUhqsD(CLcsSUa4zklb>dX zN9>@~j#tQaxeJlaAbQjjm5CtNfNYTRirt7@()}vtc?gp}u(#eKTPt!AZb=s`+8fav?aj|9-;xC}t=vY=_CT@z z?JU|5?1Vr?)S_7v-m}|tb{=dwmFv&-YD`BXmlfWxdu2j z*Qia4;F(&C+&2kPp4DoCR2rVoQAuN7e!oZ)u4!AgM2oqrE7vQvUatP&x$>-BOd=aO z4kNQxt8|*@B(h}^DIk%8k4c?760zG!wP#%)w+q)aRE*n^Yu$~H8-4U16rzA6T<@|M z2#(h&*+({iixJvueh&rPKlvgSd2nNyehXR|=)P6{WlM`9cQwLcJsdDX*5&(Wh>cc$ zh6TkfTexWovFSI0FQC2fB-ejHk6kbUVxq`hdBRbVVBQ5kmQ4Y#m+;{r@F*E*;Q|&2B6TRY2)qGxnuWU&5}n zt%P)f&`hxnpB21&lIX7B6DzPaBrADtwl>iVWrYkc0`$B^?njbabXZB*FWy#E}0Y1{W5Mj#Tj%zH@Jo=hy$z9d{&P zMPC(gTu2GVx|DVD+?Ppnytg0_`GjDJACg!N6LXQxT{==D!Saom%td%VOaikh_irL~R7k1507^x}<(Zt5O{Ltso;m(7S_xS$-X-VHbMYsMBIr-xpHjhWwr{_ru*d22T9JdoKc?7d_HOxTX#WF*6&l|1D>H!=CU~f`X6R^d4fIV zK^V4BICS(l+2UqcO6gg;EVC;z@^k>dKaJyBv|x*=7+3z4E+oA=cCh^uAM4{$>;FQr zY-TI&e519mXp8(LEL&T^`VgN6I#uReA-(u$;IkJvdtHN1!rrju2HZryTUDzttz1m6#85%*yDz1r-*q8rpIII8l zaAfTJ(yyp(Gc`i7)v8=gy99CGgWW(7$j;}tnsag&W#Pj(^ujRK{7YeY$;{s&)6k!p zzlS|Mpt(%$qCX42w05Lm=QCVI_%u`ajA|IYHy!W8`G`B}8EPZbjVz&XFrrfPGcHAt zHFmx8qZ+gU1RuFP%|_%C;#OPu5H_{*W+9HiTp&@)|1%$}%WB~+wzHfpVxZD3QCYl^GU4kF9U--4W` z4aBrAQ;T;AN3p9s^t_o1{Ls`NkMcUhpdKvXTmheAiOabO*<6CcER6LIS3 zo1?}Gib184s~4nc6|R{MGWx1W5qw1j`BdyXMlItFbd;-P3WaKc{xXHm%9yuL*e`sT z^zFkf@Ok^NG-w4I0nt(~tJc`orN+#el7TaZ6?9m#6ETujHd@~0*Hgk6!T z)cPxkMy6IVTY;rLfrOJ-A+WVfrD1|#zT}!odrq;pUSJkE)D1X-Kh;>L*~&D-S$#rt zqtjnQ9GD^a_>|Y(kn6A0({y|{LGlV;)+tJ;iedmwa?A8T6U$2i3kKe{8zJdeh08iE^EJF$rIiZz-6Z)(19kg4)7-SWxJUcmx=&LbN?p!a1)=Dl=e$!R7U zeIchr6FI#D;_#t3@c!lpaR2LBV^Gmz=>94Nr*5)_N@uw4#akPG-h| z%_=-AYmd_r^GnEUrB-I9s9BOjLM5T_^e`ILF%F5-U>mh^WGlHk8=grxjM(_bTEkW( zND#R~!`1>c0k111MDeu^?@P(%sw6Hw=d#rTerG&;7S{;aLo}2@qcn@KSSsVavDE|K z!IE-X@@~+(3!S_d{|!*UNSVF|g5;G$3#BX;A_X)@ew0y>pvD$vYoHZ(_~5PWsNC#* z?`s2#O$Eb7g$x*G$}P;#7-q6y1BRt#4$BYn8D+}I&3`RBJ;-O!uzXW??&ywTA))ja zDy%yvXSD5}f+k0R;R1ix{Is#zqq9PKW#o=twHONTpknnXx5N`~M%8 zMoHm2KN~DdIYp--6?9E2NMp#r?D50Y3Ry#DA`>%#HQsY^N?g(L^sl&-W3w|0MyN&% z%g!26fEYC7O*DgE;JM!1~w&(Q1Qpl`S|e9xL_AIa$y^u1OKc?B7VpE zNhpSz1_ntq; zeThDT_m5}zGr3p^{(ZO+3VizFZ)Mq9n2MlCPBLY@#qei;%HRk}Ss8EP7bu{N+qrWm z9MHewADPZu_@!&Gp-T`&qX~CL8XK5tMrVW3I418|vdP)#Yz#NLhKnyecxO{YxY0D$ zJg%-bJiOk6#t>dtTUAvxwzj6KyxxP_V6LjDDlRXso!`N1E*AOKM){K-kynkYs~Sgx3Zp4vbGurRuCA-A8e6w8+&s3nmfS_UrpjDX2T5wp#Z@)6<(BX@ zwc~25W|vo1eq;;}pI>VU$7XC@RYk>C1Rw4kVJtR@;i&7(6?Jt+lgYHOwx-r-NtdRo zvb?gQwhn*hs!Ee3UYlYhbv7a$Yc`q9l6dRt>MCYKns$bE;l>(Eyz07f6;&1OpiQI6 zY%!8TRV_{XAuv971p@@pAs%dpK5jC}&Eplo|Z50qPeDgx6f1${4Q;B3% zl$+WaU5ydYv`E*08|m5#tv;=&8YoE@$v=BGv})`SRo+hIx2b^mRi<#`{B{O|p{`t{ zBOFj`w<3F^!kx$9O%ZQ26}3j^8e~gdc$6W$zF^rnJ4b~Z+d-cB5vF=FJel1(IGbu~ z%eV-`GjuL$EdLxK35Ftxh!E)Qp5>3I73ju1UKZguqDG`Q;I9+t^Bd5G@H?3Do(-pN z4tox7$S;O3_!B)Dh477w9Yhkd+X#H&4f!KJAa`}U26U4L%Wb*wS-o-P&Xr~0H#(P- zRd3{m2oy{C7*|Us@@}Z;wMJvR&Q0yaKsO@X=>#I zhz5xL4C`<4{JbgSGXVVxFaZ9Dgr9$N$SbSHRgJAdR};#Dmzygp+L?{> zE5pn9=PEN=(};*VBk!)RMY~&NHdUF0@T<@YhtCJU5dO5fakb&K<_e(^QP-lksxq6a ziiPmetbWwaG{0C3zoKr38DZ3I7Q(02cv`K&Fpdw;rfR;?ToXS3t{DHqDCe=YwZ=Pw zGB^#Zj&e)G%CXundG0^~Th+UV&%v`CHC!-E5pt9G$T7j?3oXy>#sMvtxNpXDeTT`J zOl6$Lx!zrl3U4w}B)m}@=Nk>-dEz66Emalu{UOMj@cGVV_0G>?Ps^g7KH(ZYy^U(V z6HxYVLDbXpPokdQc>&yh9QBmJxTvQOLMJ|bfa3ocrThsMdl)L`4gep3SkB9Uzu1&f z;iiJkTlfX~FO_pS8=@FFn<{gad2uDD-nw})NSqBuJGEOkbL!gpTQLBDJ4}aiPQJLf z);NDYNBwrllv*y^!0cq+p<_n+Y6 zY-|~m!1+eFlEE9-0z}n+(vpg>XuQh|#=jP01&jbj;q1Ywn(8^5Ha$7p_Wd}!PVt<5 z^dQc@TQcX=BZX_+eJJPGJDF?LGmUeI&EOn*593^39>zKJ9l6{yI*U@u0_tA4Xk1_MPruo&JSK%96Gt&aj z7n*u$+#=3z{9>-z_$9EHaLp$yj>$T_;uIJM2+`#G&xIu5$azhqv=7uc(m`h&t5jTAPS}tqB``ozdx4B`9Lq0gd z4c+t&m$KzsE_>Y;Ig-$;c|AK<3{biz~%0}$c@>5i8FnEnJf6>3RnE) zFWiJfzi^f7cW{$7?dPU#`J9`*^$=Hf_!{^6k?UOLH`lp2$8K=*zq`pTJaLPA^ZQ%e z(jRVf@0`BFZ8-NU_u+-R+?F5ja&y0a+0uhvw=xd#*BnWq?VHF?(XZC8{;0_=LP)Pg+=C)5_55JVQC-A zE<+x7+gh2Wk#rKG5+XnI0q=gu*)0~0c{ zvT_Sb^I}`N`eC`WfhjIF7Z(;57Mn{K5nH~A!{3-ElBkpRckEVFal&NNOQBldvnmN^T=TwxAM+NKS z7t=YRdU}l0^YTv_TU1yyb#Bc9b3s;Q$CzH7Bf|{_TW5D?2jBS0sn6?YY~j?oi>l4g zeL`srm4BERh*j%=CoJj=6`wuXWNbX{551u@RC ze*egh7sY-Z^QO(2o9U`+*|O}}u>RsH+7RHYb9N8N_zU-chy34ltN-b`)&p-EHa`Ae zS+^4AsR~I>S^+13(Hden8)G*%KedZ~g|m+t!nwpGviYb-KYl(+bI`{9U&A~!o6SRA z2AM2#QLn*cE%Q;AWHXzS(tOka`^Ge7^-m%hb?6))l_-Zadn1hB0b5NRp zO6Q(!g?VSg`DUm2{Cu;=>npjQ(^qpZ&sxL9&0fpJ&wTGM=bSX(9J6E-H-2R;SNL|_ zGxN&7np3{=f;r{H4STrMkG^|uPASeO3lCmp^T|o?f5w%s+riD)xRZOm?l8CDlP|di zyS`&{$~lLBer{g*qB*5FpKLgnq69*1VOfx6N#}AC{ z9vPXMI55ugGLXV)7MqxsRbcKB8KQ6I>EW3Y+pPUF^J#rbT53x2*r>LVkx@N*4;+&o z+00WKe~-k(#FWel$?=H^1ABLmN>A+FFhHFu9}YtVao>Qj3+Ynv(cADA|L zczW8n?(N%0MRo5z(3IM?Ni(T?Y)VQ>=9toCoa`4L*Lz@Q5;P%o*C%I=DK<|)_<{On z%|a4;c!oS9f5`ALdBgL}DFYLeQ`0k(lhfioo((@8Q`#|E=_#qHLlQ%*t?eRHQ>Ec2 z<)s=tY@&L{_8!Kw=p(!LPDpI8x0&cB^~~^5dXtAZpKvJh zc+Q<`mTHm6F4Kb6^LZv(h;~U9wBEg0RCDpcF7^fPo(4;aaEP?9ie7M>PoO2ooZ7!Y zJ}1xa**tf)+l$=YJ$eW6?*49uX9@>T?TpINkI;TjHtnUuU)~u4*hT8Qaa^}13eOja zkF)vp%?zGSPM!`n=!susx-{>doSSTLYw}`ej(fFv`({pdO-}T->Xncfm z2@_m0PU(d8XsdDWay?A5xq(Hqxo!pXxV|L|xvu8LT*BBn+<@`(xIyFQa{VVPa=Elrl!lAd8Fs@lV=Fw1tyjZmhqjL3b82BH@Vm4LaMd~c zyI}_@Z){sdv});QD?Z}*a;-umxc<{SOLCXKvm{*l-m)^TZx1_d6O!1jSI@2k_{ksM zV5&eFn*ZK#XprmGwR8NqCD%X8uFgD>(EN|3SM3cwhW`|QSO3L4wO^z2{fB>es%`rC z@tV^cUp_VJgTWtMxl}qc+w086q3gOGvuiywJ0>T1=jhGbz6y-HXkD&;t@romdmUdl z@23F^V%M%cbnsxypF1qQ@MpyRvlX8=3A%pNVbPslo5BKr?EcedEpDF7x|KW8?43H< zx_Qn2|Pk73aRliqKyhw_@cRZ;bBWW470KuRLnn zqQ+;>UT(s|h@$I*2DLwTDf#3(dC715c4cwqj(fUQ_iQp6-%@G}N#zdOjF4qtp1eEd z$Zw}YyN6zGo%Q40_(Ky8u6t|ifm8jzz5HbdCO1TNX;14xbu-|)n9zRHg|^m!!tFzOeeoii!r3P zwykd4{CLvu?v3AHHl*E;JtzF~_}h~|Eu8o;vyVpQ-D#JipR=?4_NY|b&!?TOJu$O9 z`^23)9lBpU@M)J7ksYFL-8eI`ruy=ZM%7z=mdKlg26UNt$#+TnF^#sJ(N%v~wdHt| zu*wx5O&Xvbu)n8MrQh5m-S=Gi7GlH`W_I7`? z_V*1BYi;ga%-T^oWVdxz=&mTGvpi2Z;r8dR_S?Mhmj9iL6W5iw#&yrx*JV=h^&fiJ zfA-+zye~WKS{l%O+BeY$JooNW?me^l$cO6an0=$Rv~4?QuOVr@ZrhoV!^@KQjt}hY zFmi9DszRpR={BjECZL=4g2tt)Tk9sr^tuUt1KvJ&t#j;DzseQW0|u<=WR)~4{C?XH z)3%qc{cUY(x~BQK_Rx0k^EN$3|9pSN;I)%WL+AdYj>s5xxZSloYhPR$nB&uH$kA?i`9 zkk@K9K0SD=bVHQ2UGqAp=BiZ9{<6nc%_#}Lj{NCH=Oa(sgj}&5w&dY5_1AYp&(s{4 zbw=I)?45wP{_+)vFLkm`Dq69-jhp8WS@E1)zH{g2n(n% z$cKuX<`IsrZPS0-qv-D8Aj>-(*UB`sc1Ojv4IO60u9B_tgH|V(dUtl)JtEs_jcnx? zYk$ALpN1N^mN&Qm*?i3XAGVjb9`~bh=$v+kr(WFZ)zYP^ zX6d4R1sPs%N62fpIDfjOQT4;R)3@C{WA=H3eyCn~ao61dw|4tSEO-)bmy~ko6Gi0vtOPRyz<12w2}WMV@5k_NJ-3{hu4k zmONbj`(3?yh0Cm0$}Vpm(I+7<^=aShHG$FHl7Evc*Vz4-*sQ|uaL~t&_u9s7e5F7B z-yd|LE@Z~>P}N>;nbn3djn5XH9=zjnk5@mr_V~c9@dMH)TMu|GM~>R|+Jj%(kGs`3 z=Fr!g3-QzUIV~F9C*$1q@|tC*GFogO_+g)@yH+Ej1Kn1pwwSOaYKwNou(8K}3NL@F zdGeh!Zly^+XPF&0Dn{O=^CIqI(`A>_)(+Z#_RQv*wQ;Q%m+Y;aTpiuiW8JzQ<9@lW z9hop`{QAkUtER`UNoiDB& z$vVk?Pq-%yUOY3;g^rpoU*F@o=fYbANy9kyNWd^7HT#|oiz~uf-ra1b1bz{#JE7w$)E#D0KbG5(5cX@SrsCtTZ z+`P}aO$u#$-a6iPrSp`uDMjy3?cv>_a^q=}%JsP1&uO{hy*JvunxEWwt4IPYj z``sq{?ELlDus1zkR&?fCHe0!1@R-LB-@19csPy5PTTd?jbkgmv^|H6VFH)WVe$$Yp zKYe?!U-L1yiVh}z6sKSQ>iZe@mvy||+b*uZVpvG@du_O$3FEuVRC9W9jqk6>^zP-9 zUQ*(DrpTuMlI2@B+3#xi=KAJZrT2_Gk8cf+jaucm+o$XLLFLujSHRoj#D;SDdTRt+usbiFm2-P z#x;vaMQiL=xf~xfXw!r=cT}dzJ~Q6<@M`-@DVoc7?u`BP;)Y&tq%KY$;$D_F=#O*xPM{c^?;rzmp%io^Yw^ZhFF2~KY^A~ObzxdcbN=!*P@Z(lf zVq|T_-5i6~tJ`ON`fsS-Rr7h9KNlW*>XDI}`s<00j%#*%{cuC`XI!~y`pK&=H8C1T zv>qN8u)s$lzbxw#k$R|fxKr;bX=QgWzjFIwt248YU2cD6+VRg_A}5!B^5wW2@2AZ8 z?31y(@0avkwEVl*eti6ESo<4oe~g%P^uvpJchvL7PP~?N?osNklaE81k1I_*cisiXP#>t(kd z9f@6W>}u-O$4)=oXq*0}jbh6AiCcT!>R9X9@$6^YR(9HT*Yng%HhGV3M74NubkWn8 zcjuqGUxGfYW^qc{wFRA*%DBa|PlQFE9ul+qqt|v#Qlw8_s+{9UR#4gGrBwehzj zT?fSa^^&>0v}M4F7N<|%nRVju#3x_hN_sO-c1knkEZ4L{QD8IIH#Zvl-`z8#>djl` z5v`llEL}V;ML$W~$VbusX0ytq5xMIwJh;>2&dFA%XFl?Nb@$O&ZdB{xIkHD%7apnE zu=9RLjqlFwdlDuZU$?Vb^)XjrQhjaeAN+~_p(^dY4~|bCGki_e0k4$35ARmZ37e8P zG%xo2R+;hGuyyN3`)K^%`MA5!Ea#w<#65@NtuN&}4z0`cbX|6Na5IM%q1=h2b zx$9XwbmF-lo&J2_*WrVgKUif~X7EXQdg|H+-wO}>joG!@^F-(MgAP32Et|ei79I5E zvMI?0?L8t2e`)>XcT>s%`RpYJ4vyFOw;4HXQp_hML5C9h2k36>%{n=9cGi`-?y}K# zlWx78RCL~Es?WDqe)l`xHa)US&v-W;HPbKA{DuD8!jv06AjE_THfAyV#bkQ znn%>0-ZwBSB)WxXg#EM@PU|+bh&wp^rBz`)(<=v=>`a^6pgh!Fi^;S4+T_s9w|YS6 z4|TEoH|B(LSMdpt@Xw5fUXP1z-{8S_SbbbQm6arQTg)V-V*cU^n;^qD*I z+&^n4-uwQYH}i5bdXMMEo-3WNS#bBR>cL>&x`BF^&<@6`{C$0&gwFWj!w)BKEWPCM zV1N1LP1_uO`>U#D_q2Q3m?IChefPqnv)$&u6{h;Su)ki{f8&Y%K`uwG7C7v?Q@eEM z8+UfNt#NNY*!)4@7;W`{yu%lYLjwG#NA$1An3*W6Y+dov%kSx1JoEJ>id`1#Py^ryeI?wbN}* zhg%aaU5GgO;Dcse_Z4=Gf4|MQtA82fexgy{&!=Cy`S{VJydT%tZ|kU(M~6;c6L6qV zy|(7fwLi~~%DCTh^VSFHyV_ocf+o+?Ub}Wpvq%5ReXH_8uU`FaQ0&#jY|nu8r()L} zbNYEp+dr0s{jp@y;P|95>kGPakD^-l8gugcWQV33E-p_hnDe5R{ITD)_(ire zLe9M&ol`zMuDFIl~Bfc3F~$MS}{o*AtU3=Gu#VHF>6VyfXt(w-5`7JRef==hT({Aw#mtHhui#nMHd{b_tchs=2 z@0c0->8JK*Ki<3MZ0}o33fz8p^ZdCdbMEYNopt)q*Lyxa6PG{7)Hm|PzWC4VW3AgS zZR-{F&~JPG{p{BYUK`ahwZ+r;nHPVMxA}JMFwL%k{>ziUa36MiLZgpHHon*L{f)P_ z3`tB*{;2SN_T1TqA4aTNb#&XR1&^o1cs$+uLt-b7psBysjo&=s+(z#p51g; zj7?Q|$D@J2p4-^!bfW*S+fR&GIdQ(>+b5R63V`Hp~}^vJbjIA7tOY%ZQoef%10yf3+r`hcT(*76CVxQaqh?P z3EwaI^U+5sPjb%{u6{ND`uFRi_db^T(&)7C2$3!L`k>=+w0dfOdyT)>HFefb+!NnbU`6fEnSYF^?&zbEfhPp#d4 z@ya{HQ{PYf(hW)2dh+6@PaQ*+44INQ4nv;berrABn{l^y^~k%m$MwiB2S1IT?XY~n zJ9R}9-Dh5Hk3m9Q?+190j3{8p)Iwb4YFaIbkcJ1hwE_sf* zbmXb|X7BsS5#tZsQJfpT>gnnqKX*JLKjZ!TnKg$SweYDmcK0~+v)8nTDt*guZm7mR z*xO{#Vnem8di&!wn(m<;E?xX8x6WE^Z`;Mnee9SEkHbRNZAgr9^?!Na@RWNWr~LW- z%K7Vd9^d_jkJU`8;w#%1dS`BXx_I{(?JS4);;&ENUbkgNZl^q*$BoR)UtK3m&iP%3 z4;PhRo7TVK-S({O-yJOGXd*{i6Ebp5We%`-k#|F*i8Lw|$GySEoihhub)mlk?X-kPnxdv~Dz zK_~sNe?q&`ELf(Pyld5AQ0Z3JBM<`|rD z`~Z%@PA0pX2>FB0&qS7g5WrA4WaH_`<7L<+l)Z2dn)7d6HzNg1qJBC;ecbW&`~Y&_ zt*P3C={F=$=_CUT2sOBGZA~y=urt=Fu+VHHurF9Y+u~wc5GW(Yz60klab{j0-QMn# zHomXPL{hToP`v0w9fLC}aISzy%1hk!@sjs(PA;^Suoy&lb?&v5IvZfpZPMPnJQ8Eb zNdWr-=6cMJ>JlnfWp%TRL6Z#u#`Ix@b-)0=(EOZ>y}BGoq(Xe=SQF&QMfrWA;X-0? zH~Kl}+YQRcHH4zsR9`JQ14D)^zEF~DGSOa`hK)!$>(n}T0qGWXL#%mZLCd-3qIr6rO9Opz)uEBJ)w8uHdR^PYJqcLQE`3iDm} zdq3bjTQn{xm8HNzc4bp#@m=A*==X520hq57Oe>*yvk`JaOVC`cjCoYo)=JQ2oYMc6 zsMnPKq1jZ-Fufry_c8MsHsbKSlD_R5fjx}N>F8a;p-&GhK^2JE2Uq6b!;7wgb1}L8 zQUPYKywS(e4?*cQPZR(HtqTdloj%$=5D(l5K-?ARJw9f7eiOCC9&ycm)nf#{uRHd9 zEN&y0-&TiV{%h?zbS6txzPkff^5y{nNR*ffU7NB~A=K49*x^L9iKZ=V@R3l#^Wx>1 z+jAqz6sVHxbxB+t2gTYsp(nnWxdT|mbackO8GX9M!3idAyk=su410v@d4n-EAtp+N znjIzRaCWo_Mku_G-D2t^GXiq;nvwy&MEzF)f>9cAHw&09Ck**wP24JWncVmBM6#~( z4?~liGI7M)bM1@pjK|MEEZM6VO@H6xu5^{4&eRX)FZJphSd18AEodR2&&)@Qr!fcz z+QC%WXXBfSGe{NvE0u^$nE0mObQHPw@G&Ie!}oAF&@3kp!E za%-G%;VIK7l7FK4MFRBrKC}Sws6Sx|!{gGOR~IxQ9ssqNL%eZS8aIM2CY2uAbEC)q zu;*pu(4(`OT);QeFnYB-CWBlRIFgOEZCI$uQmA&g%}7ZwOax>i5fzA6PaeQp!bzGh z+)%izan2LRgl)&~ZI9BQ`U;in+V+Q$e>^>t{PR~!hl>Ivmf;5!VZS9c`3HW6vh&LY zd8+zf^HM1t{kbp;ydgh)@g%_=?-1{0TsQClnPjkbl5M$3)orTdKviol%DX$(4CT&) z`xT7b1u~Awn;h%@0FXJA5Ng@2o+-C>D889t7g64)IT)`@aSYR>>g5sRlRTpx0G zhc-&n{}X?^qt-D}GP^*Uxu+T5%h<_n5NR0J!XCi4y8;DT0CSn=xa(q2BxBdqMgni% z^9O#~7a`Bw%ny@#UUN_H;J@;mw?5QsbNX(Ob!?FB>J9^kdxkp8l}SZn>lwqJdIFzL zNT=+b7lF-Cel?*enn0NoIG0XFHB3TjHE@@oXNj6u@{dBa;6Mu3gCC92#RRhU>mR{i zHLKEjsCyalUrkRv{y4h{;t0=hX25UXuRCLF?R_9yRC6WuL#xx-@EJr?8SI`QhDO+i z0NW9#eF8}+VIhE}b+W`<2n{II42?g4FJ|E2ipggPew}laOH53^j>ja}6!8E~Jhoz& znb*|dZwsIwSTnnPhC#%nN4Cc2S7rEg*?;m-Z1{Iu7zGQL%+DVQ!gA=ZPFNcjs*6m#^e%W;v^HIQQjwsZ^t)6=RG7&LcYRms`qmG^yNxxW#MiK z>T@HSL*xF5NgFtg^mRh#Jh~6_5?;F#ecw_ zK`0|!TgE+S1~Or;=?M0@4WVb)zg@s8#L@XY=y*naus)n=G0)Nx-*y{YZO=Og5H7jr zQzW+aOs)hj+z*b?V0H8@_P;f=g!sP@Mdc9^IESYJB%i;APir2t|97jI;w4PRHos^%eV~d5c}hn-uO9p1!Q}+P^~kGK3isufI} zJNMAFqCUK2C(6N`!=6}QRcmy1I{9b`h9GmLV+NM3F&+xpplw5kgGyouE1!OtwezAV z;{|}R9wVShmZ1(&L*r5m7~W5%aX7jOgkW4m-cu(2^{*2~3mGC;HA_~lhAkn7LftIz zz46Z1^BcV}-!Xcp=V9(|YzM*&W4a5GhO1Sl$6hEs4rkazuC5uNp;2FG>B|ihKv4cO z`mq-LILqF$gWg8?p`d`vHbrbVz#@1F-mKK+{go@FIwf|6Z@=~=RCnNn0q1QONc$}u z$|AO&8$f*7Mt7h@5nisuR|8;3wzrjKkzwe$*u=suarqE34QW-@V>qi0f zGeeYXT@F*+Wk}v#PHf$3qa`x?uZC1v``WX>^tr0pQS}SqfMN-1R5_zW*_>Sq6ks2S zXy({y+{C? z3{Tsu8BwHrxghcauOvb$SEyMlk@gUL2`vsQPSBK*ByWz*IK$ZTJXQ1igZf#^w5oZkRf9_o4a6yU3*>BtJ=mhcFno&jAb|lyHKQOMju3Kb| z2-rh{!-B0+$<^&_OP@_uu`JT>Up&2+J1>&;$=}^-K&BBA!P}_KToI@!n_ahGA|_Sc2mSAk9(Ziok?1|d@qem92p_LT z7v0th&AoKNNF@u0>Ay|5;F+i;Pk1rX^k!^p7?W+_fJpu`1KlDXZ3&AgH0lE=%Kicoo}M!kN79Gq|zKGc@3NG2Y=X7T`tL zw2AGb@AT?~up$PBe+9@OSH^9BACgkH%{6fNZV3Gt%rJ4KQJ(oaF`M;*< zwLX8Q>H2to!LTW_Iasr=DN2(iAXWuJSP9BUh9?97*v-2eqnF}{T~dyxH zLrtC}@EL@%l44--@!QeMMzi+qyCxUkaOt%v`c_e4IK+1avi~##lrv;9S7a~{G}n3f zVxK85M?y-;v@RkTJX1ei#=ituNx~*j51%V=uO(^5etWp)9u~I?1IF~<llB4KLKb>Wv%^;8wMATV_!TAjFXz5eb*TP{X8<-!&$Wqi>Zw|M*%# zoi<)E!wAAPB`(ZB)~2dylBip5WD^BY8uEN6cFEd^l4c6?EQkBtw2w&(TkF!x08^HR zFaOHr@A`UPewI-G-2b}Ul(!}oQ0w@K0^UNrS(|iql^()+B%GMHIR~pFs}WEolr72T zsdoLaZf-wpjNf|{E8{#LXr2>#7_0sJr5#{X-;8BK7wq`I?fQ0o{+$-1w>!? ze_8;}VFKY9sdiItC|Q`ATBXcmcXDaqSsT~1IAJuOZ>??&-T(def4k1pbSVJFdUA@+ zCj%Oc6JbZ|c-I{B)@sYnSB&)YZ;=Ga$n2U8<%$${*6KWbFyP=6$HaIU7^NrAV~rcQ zMq9D2qk4phDY=6f`Gb)>7Y$ZwN?GUuz)-dw8m0ze0HMmtrMJosVS11%G`s=DcgD zHf4yFWGIV7g@ZdJJQB?Q*o&^`1dQm2gDO0+pk*1Fb4+mkPuJRU(o@cE3TkAfs?^Ub z(U;LIpP^s?vIySSAt>QVtT|AlnC$MjypL3-cp+de4xqT%KnVxp8FB$I(r5)f^P6?);K4xfAq#4S*Z z1tOQQ;o;L(kW^MPR*b){n^#Y^{El61F~&7S^bUkl2To2-fA4yO#|vGRQY2dPH<)cQ zT66K`J)s_*kE~h))U-6v6!JZB`sCcn!*XO0FvD=50vQcw;4Db?)sgxMm2S|8Lr@3i zwnx^>)eex9cq8I7&3a{q^zz((mqG$o6l-mN( z&6*!7V@U|X4i}vge+u4s)_t!vRPFfTCWUB?j%)ArCC zZ4r4q%Rrw(i95!y!?{%zrb$J+55zj`n(SsQNjWi7h9QX~_Mtlzq%*(t^ZUsS5b$LT z%nnn;QrkdC9VjTMLx0Q6eWYO&3k%4J0;aPbk?P2jqy$+_?etv?%LQgP$30yl!3xyG zon`|rj2L}3A_P4Semi4-$PFNCY*d^P3g45TJe$GtPf-5E^gB0xo%v^V)(}qkI9>l1 z&F2e{1~7N!TUfBB(GR)Idl~2PepD2$mEI6 zB%n&QV>`XdJj8(%%q&h(Aq68a_hUE4up#DgD5h0T0DvF^djH`XPy6ZY016PMYI`|Y zh_QAl{axx*Ox>e-30~i^HixJbmY#qeOp1`i3q6%dJ1&uhvg7MHBPfZ0@r~UPz(xnv z7@BpK1_xk?N-0xh1et<^=jPlQO^3w5*uhjAI&&>B6CB4fO2WaegSx%|fCEvY-(YoOi`WATIES661DpT*$7mLZP?jWs!&BQ07pn@c z%i=@&HpC_7pQsY&;zm1)QK(CZ%8CRpv4^yv?x zN*EM=CyHTDGna(QF6o?}BmhFQ7cKpY6ptUPrKZ$jc=p^aolv9m!2_g$NpOhIF= z12V!BuzPWk=rOnp=|;FktwqyOpelVUtwc$j{^v?AT9K4%P-L8CujS>etXazaIuRt` zO-k0JfF2+b4-7M3fgwS0I&fcFq*A%Oocf!NB~8+ z(zx&u3^eNumhK*%DX;=B?W9I4Me2d7f*i#;^w;Th_di`%YWLdkIQZZxz*^!>SB*{i zQ+nKgxim}8V5HzAtlS$+)azxVd-90%2x^`#o0jyc?6C!fxzaFQWKA1pV|4K-+9ydZ z#QiA`LamQ~(R*7#z6$X3h>2n!P$9llIsET2mh$M}(WJcVto3F*y=E(|fu|<39>PdM zQ_#cSCB5+sD-OG&n4Ss*Pi#1N4)H(D^wpPKkiH?E@Ul3Tyn1NQI5(iF|BjyYYBL+> zi0lYMYk*t#A!$W~q$avqeU)NBqxI8XIxftt(kiz8h2%G5=ys@l)WeKk$RzJ*Z4k6S z4aErq)|b{gss;j1xB`0(nO3`oI8UJrZ~c*h?0lGMsK;;(KkbAP_q6|eMxoCp-4`Y& zLi}$-davHV>{&|*9_K+Z%CtbRnT^O77%Pln5VTMEGx8k%cC7(LcE0?HhL z5C;e-J#Cx|R^wQ+$^$3J#SbKv-dz`jCA*jj6-E&2 zg7csNe9etS0hDj@Y=TZVXu#Ur&jtiwEY1d%T@da(AwtsX!fP_fprHkIC4a9?i$fdU zRAA9-Z269%y(|i-6;G%PTK#|*`r|;Jb^EOmQ~b!?q*rsZAknBB>fg|h-z))bc_Xe> zrq!su3quF`!3t)bTXos^y^;2TQM!Sl<;%zRor!yG7S(CNy_hI9sc}qzy4zX(eJ7Ud z^t1W0egiztaa;f?xF~Xbw9{}ulW1n5{@H32Wt}Ghhj8}M>{J-w*aUi6bRq2|`^A@1 zOhpZ=rTyX*Bkc!M<)}&b>yyt=ahMc*mMM25XSb` zQ8>m-tX9+;_#A%J4LS-}DkRf?R`TwfZ`N*~c>%Kgu2ngxr_ODd+yq~6!m>u7{!Ov=I_eG0)&kQ|8(>#CrEiy#5xzmcG#lswt_`|E@8^ z>3-v6jhdLclsz0I;7$bAlZCbuA?&V+uD=E}Y0v6QF`|`}u|iV?&mlE&ssbg@KnP$; zRp9#DX%iV`4Y*|{$8p$r{YnEsnR#0Zzu8x|>|P_66YK!77!!d4hG}pUjh0f!@4)ie zgI(0I%X4wt1zJnnAW6hq>6ac5hc+32W46TkQ$@Dsyx>=E>KcO{&3FA1g=-iC(u_X? zL*2jXxpv~VO#N!D*nd#6!Ua1DB^ba#d?I9QwuF_O*svtMy>H}n&}h8)F=40HS+_+1 zg6A@ft!pl+*TJs)mPT4Vj=MK@B>Ydl$O37Yk}YY@_GzK;A?lu7_7?MjK_#{#HE3yL z(VD1@!BU{*(UGf^VT;g1k>O#$B#&KS>*{n?mlAUpA!UnfOs|51{*COXVEphtenh0X zoRFF8n(c8GY>=Q|Awor`t9U2`QmDUk}b#QeQ& z8m6jwCjcXnybP8F4^a)-k{B_*f+e1iNj&W2eFxp^Xe=R+YKA4I%t$kj{rV;PUrksQ!$-m%tAOFev}J7aratYZ3b| zhrHJg$WW^uOMhV*bhEl1#PJ<0I+*o>1eFm@yy+=B9-5se@>|HAfiL_IrkH)$onsLv z#S>~1mnu=xxVSv;-!%gaaa(cu6Iup~!Zcc}#)RHgfn#|@jtp;QwBDDXqe2wG$1@Cl z$yD9Ojn2h09I5lGY|$w{NoHtF=&B9!*RuHq1-r!?V$HBpb#c(`ms6&)Ggg6L793@` z@+rY?`C|AZoD5|g!;pkj60x7dm-~=JzmlAv?)l-H`XI&|Ct!PQk4VM8&;S17{V!TT zR9tuAY22j8IbTH!(@S7Sjl#UZbdfR1$U!7=z6f>l70qx~F8s6zm82U61v@ScEG`{B zGH5URj6Ug#C3A8{`SRCrqaENhyucHLoq@-%Ocf0X-g+Oxr&UaO#H;fgGcdw_wezUt zni4Q|M+0*+{18W^wThl?WMqJoBs_f&w))5W^1wh!^{Qxm&NnZ};+KaBT~?hD>;{oD z5m+RthjLmeSQCbE!sog{1S*nn@)HeJ3R3rA$erfFULYzMYcbKytC)4YNg z%Wo5HmP|$qqQx~sA_Ht`v+xT1es)}l@KN|`kTGon^rZ}*-x?^+NUK5RqPwT8k*O7? zo<7n>XjYLHnTEt>s5>$_Y1nbC#xYD0K8iNTk(gBT+I?|2q7E!dgD%6ZJvoqt0SGTE z%?v3E0vRDmlO*a50faJ_ln6n7W(V|Aoa!f?n2UFUecYMR(DEXQ;(7r%CA zo$DH%Ob-U0+>qYjo0kygnuYRh-I$QSqO2U%%oiMxLg;C+NAg+^BzE*~WvBrv z_#XG|;pJt`Eq{v|zJXt@|1kY}5fiIt^<{RV72f;L7`L&pf8V;ov+>z@fUTsW96=L( z_<`hkfme0KFTd$sjyHS$D{#cZL#DgDffOV%br zi$bY<=>tIx;En)#X<8weQhopxPzc_~Q52YF9VSqKRzUol)RsMC3rv93XOxzE*mnts#O@^C~jtP@dla_1VBEK#B&PMQgGF-*CG!%p0i5GWB2ABIt^7dW6% zVrGdU-xkt%sQq(Jo8eR3y~yxiX1`A#klIkkF-y;Cz|4fslYl%x7sd)aHUO2;T~NLW zYXQlxMroi_&|)~@%}jH0tS+DcTMv|F(&nhr&$;qas5QLk#$MD!{O?izES)L=&>B_t zh@k*`d;5yzlR<(#)pqyDycdP6yPo&c0P?r&eFQRZ7kxq{O^BKw)}OCqEsc$qMg_*I z3(6F=Nj-_tEGsn>hjv?cmyjFq5cG=wfY7zLRTdot<`}*w?S>jiHMz&fstts3#g$-$ zo4HYiXk#!!g{R?@>R6)CP2y(!?~HSeP775TsN}J|na+@f)4p|Rt~tB?Dxg6MrGV6& zNa<&2+pJn)raucDN*%GLd;~0e?3ChUxaFrtuDZf)At-c3v5;V#Dn`M5IqQ*+e4kUP@*Hart~?ZJf*ZO;j)s{r+q{O1(W4fy^J1J@6_HD}qvZ3xN_g z|6;G>#5j0;vnllBE!!>04r#f^6mFQ{5ssWI`AZ6o$Ap|0%5Lsqsw88&%6lrk${z6u zwW1E8@ka+SWq2?(>@H2cQ#&SgK{6#ZYQ)}OGN|BOX|Tn_0^D0S?2UJ#C zT{{P^D{KZ*OWJw)p#?Wp^#h#7^^-owR?3$+ipgt~on!u4BcTxG@-PZSRklpEFCyP4 zcq_UOL)`L*&tSuK(WPy3_A+mGnZ*9ea_4=}X}l9wA@b1S;jG$!GktZ@LhGFl=u}Df z+=9l-mvh;v`qIyftA&;4Nt`GKxk=?d5GwzI5>>M4n^KcLD+@b2L~8(f?@eZx&)V=n z%C->o+|3vUpdZWouF51%c2CX!N@3)x{Nv=}vH^c;8;-q=EYuD1Xt)`NIw~wGT{S0s zjW$ksf!%Hl?McJOW!3kq`5a^9nr2>HSJY|U{7tIxUU_;}Q;V-N9y@ksCz#bQ)02jK?A?Gfio zYF@}N4rG~dw4wuC%AG>_Z-AqlRF)qsf70uAzu9YF{ZI*n7V=0XDT8S+n2lSV4@mwi!aXr*cY zJl7rvM?@oYoPHsxkw`H{ST)8twZ<8BdQv817d+i=ZC~!dFyJD8=1(q2{jR-{`Te3n z%UJ$1HX9}0qizR}i0mp0Km%8gw=f++MKZ*7P>UBJcusL7oKWhAoR-=5hp|nAJzVU8 z$p4}U=DxP@F2IVu-sT>PBH{hmDhL@hhsu| zz_t%^ddTa*7B18Ekh;EdIZSrP#464B$~_DM`d`{Ab>M9nV8aPNP2HPuC!-uAGV5$o zX=cS+5>a;?-*OcI@FC)mPw}6}k=*t*R!$kyq)q}sF(eTa=J^5!BB_Op8PlUE_3cTz z5A+=z9JX&v9;r%UW8w0NqF@g*r;9XeO}E~|E`>25IuCW=plj}TK7M9w==EBP>0Co8{vGn`wlG;SwyFO>1wcIXXYK+e-!k6PGzg}+ z;zDL34f9{x(agNN`na$td{XDufREGijrhFV0+8~{f`?u#dqT1BqTB*1v}t^N3Ku^v zK-L?EO*+tlWaRT|CWwFwrYKD^_nJf<2x*)7^*F>%Gt{Bh;y{IaKFH05U> zY7MU=f@129iq}dxfY-U!j;3l1a65@MNDPie&Jsd9m^M9@>4{}5NpjB@Z*mpuzk8_> zmtzW-h-N^h42PL%v@A^Fn#u9Y#~9X#AT5jT$27CV8zNkA220fIHsSCX{D>k7v%I(y zW>={L{pdM$9(GL&5>2|FF2SX8TUcl_5kOC&8H?!?NRSgor@+H1y9(?^W{z+I{s#H_ z((`^LOu6lV5~`1jkPKu6s}CMELys=Rr>VCwsv%J*ZOB8KQ^GS5w(uP)(z?6=6Hu0Q zAR!p*5k0KA-T`%>S;?aL_f>y9O6&LMkCz%^HMR`RdfktX%j2H6l=TAYPl5YMIdqFp&q`7JcR}|6e?~ES2_i;1q;$=%jjK* zapZfMP~23gm3Yysuo`=^ZBdJVGgP`4-}@Oog6zec(n_AqEGW{ODuIk=cjXAP)yM2N zxM?I;&`sL^?mCXPtT|+<!Xj!Vb`w@_v)_^En0?(~L$J#Mf0I1lS8#&N+4 zkP_(S11Ar&>i-p8^2V< zM6>}tX6*(F9$Q#FT`0%ohX3+SVLCj%aKSINN@f6jRndjd(-FuuV0d%H73^7+t`G$E z*GUwg3PZjjo$ZBGe44-X+sCgAiWlNl*D=+$q-0O?QHuJsM~ffzbNbYZ8kyaPdbAW} z?Ozaw#pPpc7(}uNMVP1SBWdO3MfyJH{^nRiAvr!ugt|+@nJ5XcARg7SRf)ap6oqB=xXp`=#A9 zx^$UZBVLj~#`K4^1fm4?$W!=|z7!K25K(&E-V&OeUx^#t8CvlAt<34;5}wkBj{^fP zvH|v|9@-BY2GHlk6n<;@L^bu@*&X}YtbAEVJ7k5pI9&sSfe4g|(4?gkfy26Wk&~ir zJV9gEnfjTa%k-X`u#3lnt&Z5%1K7+yEjlRH5|xTn6{hUcRQ0tSLuRyb2e7cqBDKpL zLj2O1ybm|UZ@35I!VTmKhLE3B(oYhOFs5)}O z-rp)$?S2JBiLBxIoW;QG9aFFb9g;M#usuJD0}&$H(~Z>eDZ@q19yaw(DI47R zY4|yn*xGJlFHty@fzPE3R^Ymy(XpD~i@p6XODf7T#r^K1={`Vd1CBA{=S#lQP%uul z6OBukOR2v;9nz~LRGt6ERC`4nCUi!mHIR|!hfC#xQ;9B9`di_L^7NCC*wss&WFK>l zPg(ocWt_&xUYXd{`~BiC9r~Yb$CSabg0u4UZ(muHX-Pr^Viy{WQ$`L4sx%0~pOAO| zflj_799DZ#jGH=);@FcSol#!l2@P0tIoq z-5JeD^(;%}(qQIFl^TD^=x4@_dm@OCNU~;Xh$*1t_Fuiz0AdYsoaUa$7$xpBVUA^0XkN9eZg!4>r%5YyE$i>^$p-j;n>eeS3xrYhT z#zBfoN_#OH^m4ygfAI9vr1G`GzuTE?W=a^0kh@)R>lQwzC*W3~JKph1E*Qhv%XP*Otb z37XyVyYP2o&8X9SiNha>=KFsvAfnPA8NCx8j{{YXMXIAS?9{MjX&Ke2*sdvs^&e5P zY@AM_v4ve(%r}*bOiby>(*r*?tlA-;!(B4BhLfSUhp*>d$XZzX^ghH3!sU*H%LP^VDY`LITQ+`%Yk) z$6xhL?L2KFhKc50On>PH&q7y|i9gKrx@PvZqx2hM9)x|yQ&oeY0UX?R#>!mfw#>dB3^ZU2ALdX_|?@4te8dKp$G@+pI zuk4~ut7w>%;xTMrC1Ck{Bl;?lj zKojWsaI-Tcevl$`S_zzYv?jJk_ABP~Vhw6P_SK&2Fjbm^ON}zLoEWePOV*Ee#%{1x zSm?axPDli%#ixZuj7GA#t?T_BoL)apyPi^M4t)+E#)Ozp{+%D?pJ(??nz8}70Z526 zeNw+@&wS-4^!131qe$OjNQmG2fDPYiO0!cO|hIv1s5hrA#@p zj`Bq-J3CHl$A#Vo{C*oOj-d8NRwM4kS5#D1Ltd5s=NC5tzxslUS+bSO73pwfODLJ~ zwe|G$cFw#u=`LYyAZN;Er>EmV)ap}9*i&WSgN0SrNzN}g$l_;iQrLa_f24TGQ*lv(;DvuGx1bRIs9r#mmR0VNL@zrP`ZZ=Xd?sb5k>OV{=jGeMtl2U~F$VNU@>? zsU@$560x##{gH$&iY1X~q59*$UOU>DLX)kYffv@7^uVvtg2C1O_7qLbpTC?RrFy#? z^u`}_Pp892RcqX-OfmwNmFoW~iwXNWrSkF3*3k9v9;B_Kqu1k|+2m+2FfMHx2oI6nyO;i*{|bRXCwc z7pB9zK&UM34dKn=5mV?;Me)>r)W4Cc48MY{d(#%(FoTO5Se{z9{8D=!hj1rCWv7+` zaJSy)Wt=uTYO3JE`hq`p61U8;nP&jTzYZ+)F1^_;UMT1jo_GW#!5yRR+4-Q=AxbAca6aJrLAi( z4E4>xEY%yw+S<-)R-wn*p&=AL5R#a$JuoG9i*F)=e%tSpSM9U^eFS8=Ijd#R?pOcMMIJcnB4EiyXusk`u%v5j zd?56(i%`H6?52PCEQK!ms*?^v_?zmO(udI4wiI_sw0uRhoPGM1^*#rc7Zw0STJ$i= z)W@~0v=zJLy=$_A*EbB@o}u`$|7s`>3XotxWyQsI4&IN(E@=(jf9&UW$q{JwU|FX< z>XupyGSKGn{d<%&<}LY+hDM&sZfpKq2Iz-vzoxKB998^@jx;6HZ#A&E6|0d%R9pj1 zT5hOa=d-d^Ze2L}EJe949j3=X3YLERb?Z--IO86b{KJmtB5W`Qd0?-Nz~7%j1KYS| zn9s$*zEiu61?^MM&w{q!zCxC?w{S57GTk0$Ag0UHb$a{KUi&cp4_uKM>dHk#dtSEc z8f+eCQ$H*apV{Hg*5&1n6h!1+G6$K^Q7$z)@G;uAsZS6HdwuyBN)*)s95zk2qy8H$ z%4;7y$6rZM(xNL3dys#=*pbm`zn#Z#zs08M^7{NIK>Xofl5w3JE9ws!tXg`uw0XwE z<7bY>uX;>XsGu?l+3#?g4|;Zz&a|7oEsTwn8C?nKh&(G#wG6&2*wm6`~Xe7nm<9LEduZ&*=pD_8EjgFYK-VN-tC%z z%9NzfC z0Qn2Y{MTcZiptnIo6*9p5;2w-J4Spqnhvg_l`P>&ELkIv&qbDaSz1^*W2mpcd-8D#bl}?V#zj=Ac&)yjtbyvkQwkw|Fx<*wh{;2!2yLrf^M|`^T9r18K6GN2A+F2}s>9yY+Y_Qi=jt0G?tp;lA1uGL*}H1c0kbPEA-l78gK zUo;gl>J5`~VuZv%zuRZLdCUd#=52T&?q%4`3_EUIsmr*0)n zh!HqmV)DUCF6s-}p;QSL5EP=Bl5bpn_{rNuh>QND0q635k}DMq?IHue`E`ujj8|l9 z;6|#FshkO$kdCIfdY`vqJgstatb85%&AR<}hKcFXQ)ZhPg5sLkfz1U>OKVGo3|0sW zdu94zd$-FJcFx$UH4}VRIt^5%bjNS(HtBiF0%WSJC*DDEe{b7krGi2yu=Os`#cH&we_97g-qmNKrS&$aafVgVxERp z-p%pq3=WEYf0S!E+j;BVJ#PyVd8yJEVL|`Jsbr!D>+7~KS2I%~A*lYbnD&j4 zuXf@ZZDSzdpCIu+LBS?HvOoP3tB6hZm@vuT!NxB}o~^BLM-gEDDJRhp*PjkZt?9LV zlPuAdR24KiR{M-VmUZl%;4}5~&mb&~QI>me;e7j7SMc9&zD^zMR&n*}vft-j^5m|s z3M^K+;fpJbM{a~eIeM>jdcPuOT!esdY6D%*`Rm5Rxe82I*+5H~A5w{2Cn+jIf9ok! zw2b`o)i_nRXyv7&KqYgtWy*I#?^Quh>^^tRTl1rXfju*(9FS^N7$mw7`}iAVZLw$- zU=g;ssFjhCiDWRd$G%ad=!e?!4vxYQH4O?XFs_^M=AoKUPig9p{>y-Tw}sS79)20O zrGB7u?a%i5;{JAUf>Q+7x)JT5pF%H1qJtP5n;GXG4C++hR?*D}J7e8j6_r^l`y#0L zuzpG zK!xQvTRocLSfvW`y0e({2N= zuV;LKAohy#o+1 zMbUJNGebSP(#~|1&kT3& zLb#aEcIFpePz1A1Ev8EOvsdTWGp4|%BI2H0(}=M-KL=+KD`)4#z#jJ97am$A?C)2v z!Ws+LRhlu_{^_vpMpp%YKi@{tPIU}j_`kHad%W;O1>>!xEJxqId%m!)FUN>MEjS*Zw(iw^DRNV_^Mo-9tpX;C z%*bK@)Z#0QUa9!&0wGwKb^d{OMt_k!$eDkEvv>lH7*+)P7n^m0G5-vi40?T8vW%r% zo-ai{1zl@C2g?oDJKq`cL9x(GR@lz->PJqtit0F!L~MafN^2T7eouhAg~AFa@IVSl z&QBDWrF0>&QKepZoTW)CCu7ud_m5Lz#md%)F!+3j{qwOWA$k;Ql+>;_kWQ*dvpK9Y zgYANqZQ(c!^IbUVy`uEf+UqpG$$kXBap~5{^}FB2)DD%XQO}d$Ry&|Yqh{+Vp&6Yd z@X^}+{$X`9P*Nn;h9{@G+ISYe#PK9GV%lWrIjr z0x_ruxZ&6?>394^BS6lqu_+na(oJ&UN$qs&@(CwdA{?CVH}lm`GIYY>yzLWJk6(&0ZmuGc7lV|I#s~a2phhjl-RvNeF{vFd^c~#J(jn(6_i8T(tB9ib)1V41yE+aBRFbCa&7AF^&+k4Q*HMQ@4jWQ}Op9Cd!5 zJDN0XPcHv8<8&%u|iXih72PPAFv9Usm zv^KOA>*y}Gb*vpHr>!p$5HVd+757X_%dV+JE4F2a;?g5w&<$kJx`UMUuxA@_sOSH3 z!tQpm#0ohx$GPXNMO(1@0tdd&&}8s`vvvg}Z7s>*i4?OSMAVdXRW=D}xQxMES?E5J>v40nT<$f}NeFB^R*0PNfAZ=BhzuD_+b%kCFHY@7e#@l$ah0t~zzwT8DVD3r!pqWqwV2uNc8D${ zB=qa$ypu=`@t-X7;`{57V2?*Fa&Jqu1siv-H;)xpe$rtMgpFywixc*GL2J08LpTfI zBNyp!fg9U@EEK)^wO>VEde@Se~p9ke5u zV8x|=SlUm9cg`S_emIm1LB%0cL)WX&DgK@-c!(0kU63>oq6!!rtgI8kX^dfdaR(f= z*WIwf=znTy1sl-lE_r{#sQP5QY#~gGc_%;h%x{+vv!ec(C* z1y&*$|98>&;a6x7-{8FrHqZyvPQBJQaIK;16NqniM13V-0*llZdcmZ`^{#WJ4?E*+ zOEu%7zP`Ti{+_S)r}THB ze+_$(LgOBZ-zHDM7VST}9hyf1GH^Yc9r&@4dt+`}Dlr#hs9b-Hhr67)86s)x8U&3h zJe(shi{a+EroOibk1%!xlCQUX78ImX((v7&hL@5jBGPX-rG@SH5P_ttqi({VQRcuS zW|96H&{fqfsw8}Pk};Y?ioseYp`wvy9!fhp+V3mju5Gca4b82obnNB=JZ(c30z-PMle9mEk+w!dL*{cnU9L=^|Fp?T{6|3o3O(q_{#^ zGqIw%7IDH6fk+JSIfK+Tj&0U?>=(9beXIY5CL%@0Cd)|qWYmgr9MyS}%KGj9&~(;8 zRku$YKfs}pZjtViE|HS%I>4bj1f;uLKtj5^ySr0bK)M@5y8Hb;^UjZf{}`CL&mFth z_1WEapP~HR4v}W()bS+p%;SaXoi@^sYn@EQfnOC?ml1$PK89llOEDm-aJ&bWo=ixn zpo|>NT)L%)05(_mD>n~`ISC9<_?0-AaYOJlN7L6zplh#?cdmTW(NJMeNNsfWR)>@rG8Q|gCtsVcj6i}@fM>- zDZTkG&}|iYQyM%!O9h#IaWGVJ4oY<>fX=I)nzKYmZ>KO%)O_G?q#Gl;#mM!eA60A= zC{I4KFMTDEx%z(%pbae^F%I=_( z%EPNhn^Jn&5RrsxNFkU3{_$qSy`ppwvbH+@Jw0MVH;HB_76Pbi-9}lf{Y|#-S}p`* z(s}K+JXx##UY+_rB)=0qDwuf9I*fF`6jx6EK=Kb~SZ#)SPv%p|SJ}=aeBuW`%1YTV8u^~1BNK#-R&zX|V5o-lczSbtQt<62x<**QG4RJ2!s z%Nb28!}tQB-S^_ut#lXa)d$fSD&Z8(f-m0W7EHel>_~a+JcNQIjBLB!l1O7JExSk- za!0{VF?lblNCF~n7mu)<0ylly3Oej7wL~#Pe6uNe?!jkI6&1oU3oVL5Czu$dPAyNM zu{tDcis>0A@YtPch#@6nQiDrOKpytT?dTp%>JO`j5xW?;Cqsdf6;;EDOh)tE?hKoT z{@;EOcYcqoZw)2C=~8ZDW6F(;58kpAZ(c~xpI40l6f#PN9^P-OIc1Ee>z#C=)dJ|E z3f|RpF{H{6yq8}8Eqm!CGw1d|{Fmu{tSqJ~!YQ10LZWQx_7&hshk-(hKL4c(376Bn z9o1*Q*`tI>(R4tdy;_^{PRjdb)x6@2j&Z}@Fl;(C#i~5aO~#Z3>+*TmW73j~6737C zLEH6vz5J;fMV#|u57_L6;&TjPaEtpQZ>Kk8~F(T>6R?9I#(7dr-Dn_AU4%+#^`g z{%64xYTW6k>-Ipf8kQ&Hm|fFtgoa77>QK{H=2kQ4vUbE&8q|lA$Rer7unVy(HZ!>E zY=;=Rv#e|%HbEDi!v@u^;}< zhiuBl<6_PZ8-ujIvvE*lUvzxlYSx-<%DT35S^cj}99yQM^lXClLREcJ+vx2idXQ*# zVj}AE?Azsr&!1yghqstZU)0Yewx^v3G@qu*K$FXNCfx_C@&2$u-Cwfka6Lpj8;4NK z-GB*`|4Fc~>!dLl=mWp#Hilh3&rnbIQ(ZAH==;}2j~42Km+1>qmo=fQdGsmK(J9fs zl)5`ZH1k<+jKE?EJriBDjBPy$7Xhm^uW6spBp{p4NyfJstt!?~Gl%1~R?|KrxwvQ{VjF`N%9qVu|6R$g#gN6BEq6AlW z4F7v_PFY(C6=mZ2**ihUBcShr|51Ko}*5188VCyjbG zcXBuVmw02hXAFuP2fvewhrs^0e{YUbQjwtF4y~M=+-mn5tKU_#oyiL2PXkjxU zF+Ys}UY5JpPp79+qh4T5@RXhcsvjOj9XFJg*{swO z@l=knn^`-DPcOUC6R?mLE6Q=$kWcs#cfH^OwoxIUgX+W?pde`;p+lGEN?t})beW>tJ zv~yS;X;igLWh-(X=%u=UWwI5D7M3u`>t{Vy=UlWt-j+VvKQ5QT|IURKwugI%ETtS< z{fgDsiuzI&%A(>8{)*cX@iupW5eAq$tfH8XC(ACxQ3&0yH$J|%^=<>~+@ILEbmZK# z08{BXY{PT%al^NzlJ#FP^e#SlQpkkteiyfAyNr)DCokIt?NJVJIWYog8+ryVrGLD3GR8Hh1H-{22#*6&AobvGBT~>j1dFSzsq0Y<33AU zJilZ5+H@V^#JGXaNRU-2bxbA$w{S>mh!wZILO6faEtWZ#G^Kik=t4B`a|ZUi zim*Xkyt%11m7}U*@Iz#u7wk3{dHCzuBz*`tiAu!&d(VoUL@G6Q<~03K{h#hO%-qh9 zR_g3Yn~TJ2*@yxm{0+zx@WlS!v^=-Mvc zNL*P+qpR5x<3XdR$_+bySWF=Jn3^St7E4?DFVbzlqTF#}mYODfWAIqGr@RtJ*Zsqo zt9||fAROq)q`Fb{{Er3jG+N>D^78WhUXqqi5J~}jCdtU$7W-9`P`@iT)lr6@P^a!P zdmEjdcYm0LK~pXxk+2I6(!0mzr7D$!U%x<;fMMu|n4(+g4e*+yrDe`0KV>*z>2}T) zjQ>d3NwXB@6wNY(g?$j5I+)Wm$frl~y|`*VBvAnC_hOUNr6e*8x;2}^sz1*w-4-k1 z_+o1Ks-#T#*qD4mjZw-YeWfSufwHzSY|-DU%<54F5&2Z;K4=wZX(m|AcO!gOGn(tO$BKa<6Ui5 z=3VYC+~w0~XD*S!I(jp4sc?LG+V6&&F7l;gt~C1W>Ne9hL|f0y#gw4BHys+-ewb?Lq;(a_R4MA@O+uvy}4;9 zO;OrAQ_)vDJ@vtaUOGwB9ih~k$&uP>akWmdrMDv|`}$F)nx!fxee;vdq0%L2+!lQ} zabUZPXE?-{z4?L}x$o)>L7k<898k6T(+9#`;YJ=8qoW9_V3iB>MoC5~hg`+ha+9N) zq!G!C+p#L;s%t$DFc|8w^4G{}n>+jM*?N+34MYjQ_QW1|#VuJ#wwrk(<~iA#=Z=F7 z(h9WZn+U1@Rs(WA`&vE~IyyQb8bX@#7i2whIv6PxacB|%_X{o*u3KV)DYDKSet$Dr z;n^7xC*O|??llyFKm>iCkv1^C=SefcyLdyaH3@yDTo}qD*f2kYMRr~|;cI!K5_@Qk z6_{LC1#nSfrE{Z}%JGJ7-#S1XC>^h8>I zW`u4xo@YsV{4#Q0|Df=_A0Vgv1sfO7QmF4{M^`2WOj^FbXcqXG0-Ya35&P-PZIK(X zrMEz%pcbXd6cKpjEDKFS3+v}U6T9w5wO+L3f=7}<7X#n`pxdbT)J~$N&=*Vu5*L9s z1$W|Mt)#)}X{;t&Cwu#xek43cK%xIErHt%=IgXQ1R5yMw;z)tgYca8pU>>)&$oxLd z1Gy2{sSvPoe`V*Y4QcOAd-keq+k~q_k%F^C4dn?gCG6(O% z73%#or+l4~+rrz-X_wPmfJepnmD+qthurMbcUvzAy0;Xo&dSDHNQZ4cY+TH!0OMD7 zw8lK};}0heZ$CcC!Qw+{rMX_r{{5$09rk9@`gNuC#4A2gD!Pf0gpYlUz?Cw(mm6`S zd+&;C>ps)2B;d}bhOqDkq9?R@wZ3(AJ-YD}Z%iYl<54Q3@Rb7qiKwJYBzYL+4p_*~ z!+kQ&+`>_)dENMrk-6JEdOks1=fj*aIXg#-rFQ%>uhe%Zd&OrJ3vOoy{A5LMfnnRDY-{hiF~f+tnv)#X~8 z4&V*tzA&c{yv_!{G@NAE+X)Gc*&YPj%F-)2y(k161ivU@pId~VDLI}gt=x`;fB@WN zq`Hf)csV$@Q5iLo5n?5`Gd~g+ka4NA#V4d#BZ)_bsWc3_7cIJiC*M*0m=~)c06N-) z0n&UMzf{W;7yXV`MD@Ld>D#*k3wsguauqwS1IdW;ul`4+DHl8<5XI>r?%g}SBKkkA zOIP4*2zNg>{er#+VuZLj+tYX3_z^8HW+|z##iogPIvrH;eAXM!Ai*gso^*A{ULApzVq?2F6Xvr4>oM8BzXEW%Ty;_D8KUq3RB#jl03lg9(@Qqq_3xQj2z% z3S)nWHo(0B)lmTMvD)bt<6Axa@^p7Z@-I>-_HRqgN)tCPT~5MoP8qB+uCfMO1`^TZ z{DS^|;*@u&Z*%0amJnxvHtws0QL~b}4XYYa2CZ`>Y$yG|eywl(z^V)d9Em1LgWtfZ62FwUa~ zQp$hyX+fB9+WatD(S`_)f!yAHVQgqF8CB+RC4!)w&;HO#eH%>(stZo70|%lXw}INh zPwHCpD;3<$R`3i64G}OB4X-Y!{P{!v*dVK_Z(x+neFadgTHgywQNp^8Ix$QH`5_!y zlUz$WlU(ni`0z=kk{Xfe?9u@<^>QpQMf5D)7)MjKVDFt^*ZI(Ul7^M%y>vT{OvM4a z9S?d|m^nq=znChfcXJ6jb!nOi@#6FWQ{AqK3kH6fTnbBTOEBb$vJ$#A^s98pZ&s}V z_46|LtIqudYp3;T&XR0_}Vg9LE#%9X7RkwJ?bf zKSci2!ChK~IiFJio4Mh2WwrBy#BAQIa}sT&&?0%7CaGsBFoSA`A^SdIyk)joM&Qk@BSie2F*(M&ulDL;{%Vh%! z|8dut1y0NNly2y=#Gh!g;CLxR0!QT%En=e44-%5fviPF=XJ$A6<*%(xHedhXVd0gE zc)>T@{wDH|(DT{Dxu&qWmqpmLWkI=6(eH96_0h>|&`brkW;I;C)u5&7h?-bav$ox&A4k7GV2Z36uA`Rlt^Lh5+nZQW(k?P~PqWXaxu&_wuD@?< zJ!vrAusV2=m@xjCfY#u<$lp@-^cx*8RqQ%%aHB&D0xLl zOI9SopKva>Bwds7 zeU9Lj-`efVP=@SDaIo(-4I{ZDeFi@#GwD>?&?LRqN*_u-p(o(=(-d&5K?3Mw~x zL zErl73JLordqDjgo=q=K{Fk52~aHHh%of4tO-1BMsSsb)c|2;n9v}Si5mC1XLsaqk- z%*M`+Gc%$rmIITq13OETh|+xenZ^Wfv*$U6*oSqaOB=W z@Cn_CTM~iO%+p+&8uft^auNm?uQvoz54|?~&pGg|mLi-VsPNaR-Uc&W-}%Z|_+>MX ziGQ!@_;G-`g)JjSpenj&%a5h+oJjdCo=ytX(hHwi!4!8&GE&S($BqLyis}+&se#-5 z*+%@v=$j!cegn&E_z%wM(~}s4F3mZQLQgAaoJ29;t!)d^ zeuo&b6JEHx0#5nvPyJl}xQ+y6b#deUSDlD|>*qM$`z0V6LOHAZ$0br$25zx?>6xQf z);H)Td_~IV(x`+P##EmdLI|~0N6)Gz-9kr{6Smk0lWi&lp4ZQOQzi5NvvuM}OefQ! z!5`rgAb6Cc{>5hZ1PjLhIxQhFdPC!250w&vW|q@82fdeg{ZA)e8P{F$^D?r=-!lDp zb5;WXStc!xI*}|Ca=iZG%Ze*P?hnX0_|~Mo>V9+uLW|)!SiLOVGt=Y7yn?0iN$y7D zAdxQq@RL5_iM%*7p6n0?;W*?5EnbexwLA0A#_?s;SO;E}5gYMJY%p8EISM=Xj~s^_hc z1vrz0WwgfBzTpj5zSh%&@NfC$U^4dRh0Dj@8t$^yzX@(oljp>nLuoy`Uf}H`%KXwb ztoaB5U-n!u8_?ZXvR`=2vg{k4SXXp(7Mm10rwy$ z&e6mROlRxzlZts)Pm=AO2H;m8Wc|reCjvOgw!!cJ%y*9$E{9dFtZcU*BO4g*J)kSdO+y#^0&A>V9h2fAJoTDi2KTpBTh<@)Y)1Lg|K!B!P-`y-#+o_PhWC~yt-A&Z8{$FQm^35M;aO0}=6)^FI13vNc_LK|LwSwCD zeC4`}_F=_jQg6*0Hg|q*!ZkGKmIYg=K~}qb!kFbA#w~v0&Y|^o`KK^IHhKW zF!Cd}-irMZr^H3Fk~HI4cB`6hz6JvNp+^M)!Yv)boV4OX)dm<6?S&p8PX2C zqFBOPjt}ZuX`HGhC1Q+Y_@~6QDvfoOFF5Xpyfh43Aiv7+`_BfyHW2zbtZWM~q46c( zgztiIR~PEQ9~wPv!Z;0MQ*U^Rm(&w2!=eh?Ptc`WvgA5dEcPxf7-j;L5l(o_YQNMs zid(ma>~IeZkXM&7A&6l)Tm0FGxDrl3oXIoYPvUQ zqfH)PD5PGn7i#To>`9Q|P>1o~aiAEQ($0;e1lQgBzuL|@lXKI`uQA!jIL=P^`rLH) zUPMb4+K;Oi6B-ENEW5Tx9{2Hfy-IvrZ~IS8Pft&GDx8gvD`vD&HKcy0qd~J+cPYY0 zNJ3!GdCDEqrPY$z@X~;}X(i@2WAejx|AD!x82UG!`OfM%B@#G<8Rf9wi*c+EMw%4S z@n$leNy7T`saW-Kaa>4-r{!BCkwj}*<_PrDXmLYwkn24Gzv^@qoGas(KKTj*X^c5T zY)C4;zp>^M#WA~QkwU{L9Sx);G9C*bpj2WTs0{zxx2?r4`jM36xI|6MC#7{gOY{;M z^FFYHa)P5M9yxmFFhdH0ENeG)W&b&*T(jB;STpkHo?%z9(3k%rMYPZ_Lp$sM3I>R! z-NFUJxWBb!is|t}3V*uxMc(@{O*Pm1(8gi{3 z;m1W1TYzWq_LvL^&$M0u9>H|*TKYG9gp`^Qeu+d&z7~NYS2I_HnHIBrcSGj16MI)8 zKv)JQWs1P$W$^xuS~ELjN^@%Nv83unD(cK{2MB5nZGHN++iHex_o;Z?TfT#01AUSWe%*)9H3L_I(;<|V8Fhw5jp{LY zf9B;YCV~QOCbB*eM}c!gpWk_VTreejySMPKrw+yy6x7ux(+n9h8vZ9en2O@C?` z%d-=XRN8+oC^bE9gFpOxm`Z;&&|!hQwp@_qqXhiwX%@xlCwV_5QqF!%6ciE6j4R;J zep)^5aK2;BeDM)-Ki?!YR(%noMVYBErtjqqR~@RuR;ykpWz2jqkZ(#2%>1}2tU$!9 z{Tv?`963)G%@iylDvVlqC&O~nsuaYRedm6T?RP};&F}Qxw~iU3gWhx!QqsDcU1Z<^ z$zz6UYtIm9so**qN0s-(Pu(#@c(W1}v4ZQ5hU%ENlIYljx>B%l=cuZ>&hbVCDM$tP zb2{bHP@Y9u%EC+gMTAZ^=jX-6l#LN0oXPo-v1QN&isB}uqN#!<*k4)AO9DK`ET_Kn z&B0eBT{{1fs7CsPJ5p>nu<41LWK#~2Gre(w9oZoZrQo$&2bQ|)Ik6gqIsbQHmL2hg z#{oFA-55Rbl?u93J3&(0?g1bBerVGRhL+GGE1H^_U`^$`V!UK0)5MPi`&N%x82CgH z=zIU%GVGb(r?pBWO-D3D>7u0J=EtAwyc7@p!k+l>cg|W@S0|sP8*w<^y{M=BVE=@x zy64ATBC5N_=eLT2b(z3d8SR_m5IBn)FeqF4lRaaK8y#F)B|gDNy}@$f;n$t)>2Hy( z_C|zto?Eb0&H)mV0>g1tIb|%7r+fy(N#^0>^5ltTGJ=`d0H7L#70rYYrQiBO11jpg zJ96{dMf?C%J>}0~?)2GCyZ!?!lyRgbqU`V_?U;DUJ+?FWN7ea*tdfo{GwDA5gI4Ng z6sKidpyQ}OV)?HPvLY}3&OI~3+_Y;a6_$3&GKc`b>BJ@%Z0;iz%e4(GA$W6cK|daX zm;2nrO9uNpiJTrX?S9tFYKDB1#wWE9qJ0=CSxt_K!ZZaS-m6_Mk#@evI@eyGdB}tj z#5=n9Hr3YDe}OnzL-`-;$qo5P0P=rvv1QkCaXolT&QzK}9ury@UJ za({IJlB9ws^nTG8(X-?~dBiHmand9L0jzk->k+|32kH{CNkg!IR3T1*=1E7YgHDFA zu_>or5q1jjs*pr{bF+s;#~NFm`p1%)To3Q~fBg+rqh)2bI3t>Daqonsq@=Xz0WC?T z+GL5R*>0oP)kf%Pxg1dH+}`XzV9q52{^!a`#E$eYyY3B(mu-oz2c=ieP{gyk_Rh*H zP<@ruoz|iu%9HVX?(fkvK>br=qs!@X#xn5YT*PZ9J~sTG<0lt7w;xgH!Jvfl6<`QR_%_QtGfU@$|X38L$4 zY5~IisZl)p{in%JA|!KeOL*^Tl%DSoL;2ltJ zKb{M++p%dqkSMl})=nRvV;^|VQ4J!Ma0^#jPR{J$pNB#2( zY;$x2BF5q^pO6#7z*AgAW$s30?+9m8&kYTy`#n{tsfrITlXd(6>hJZJbQ1Al3{9Y| z1^dc`SWJG_az2@}E1F~(MuT0YscAoyfHc|=wShJ@Vs;#7|N`u|elaDIYdak@@^^J`oW>Btlg|9~6nZktb@4w>XdaLmb3SS7hdd{JyKl_)*!Xi z*h&6vLSq@p2}(#d3}xHz!HT+#AO5{DEJDOc5~BLUTsjXgUgb=)#>mAte;Ppc#XA9= zKKYb`5bgd-_>E$=1*o@@@@J8b_*sdA-Fmp$>KdvHVz_d6H6D7a(8|Uk%})B|rM)vj zS1S~4pU(1oO8u+g9f`l$lR_t;JH z8@tSz&`LT6KObKXJqqBIHnLGy%_=yeQ!%0$dgX`JA zC2{M4*g|_O1K8dLV%Rrp<6wqyoZyteDo1#_>D1ESk}P=Z%pAy($RiKzG=|!~v#6>4 z%7oqlA2-^iGN_*)7w(RnqowO31f_P~M_|i-p@tCssjUQK!P1v!v!B6agr0t4nhcw* zd=WP76=s+hKDxodTcQKOyVlxbjE$aqE1@<6gRMB*PU}({OU1 zwi+$C!e4Sv2h^>8Yu(~$Z)xmduDyXgGnvl0rHx@%5}>%S>Uie(2584^F$1X*t39HR z?qWl0tYM%CBJyctb&_q?@%YenaAcaRN;M>I0HkE~&tK6Sb%U1nR0s!*nK1F^#| zn^V%d)&aKKKAc$Y+CFauXm8NHj`(>xiu)gTxi_J-zlGYg9_a-6UseBBFVJ#o`uN6PFBx#$(ux{ZY@@u@3>k(~-|-*^8lsErwy~ay zxxkn=9Mc)SObqB4X?fhdO2oie^SJzCcZB`BNIaX<2h+^@#P&EWv{2z#U^S|Youc3E z`fk|4{VCIp5dD!_hS|i+qf&b2H&^;dnn`3ick<2>%+~-oCATNxs=2q8k;a%hp$NeJ z{xu~qWOd;8uki{3!b?1n)cEQAy_mg;YSbX&PDxKbL~k6*lahNFkw>nenwo-5V9yc( z-gAMnfB47t_Z#5tYMwsxOufy!41LZZD#>9A`N7KjwqQqbl!&gNTxj!|5r0nj)Ib9+M%{B6sTyD7slqJ!kW*@IJ4B7FqWAMj)y!2eFzr?Z+@x zgrEiEh&1s002g>2&Y-|jsTgWvh-M4iyCM$5g|F!>EM29m-a%W^0nvW|MbuGrTYF$J zvA7e>qIXScHsL+*H=t$Q!%g*Bed~jCM>l;iw?Pj4M>+Zk*%WJrXEWp^`1qE*PxKGV z$p)LZl{(&M#lrp;QcDcw&GdvyYOwoWb3667pKN{9?fQbxvkJKsoh~Xvh9k2k=`<0T zQJ#X#%WwL6UxmWb!vIr&5Zs2185|JpHTW8G3)()?@2L?lvb9#XB%h4H-pBR69ot#W3ioa z7c4k%>BL(m5Fd*l0NA4pHh?`23`V{4^?4J*5WcVN5{jc1a-E%QnaB zw;Gvq346QGexV9v`x9$!j%x_?ZXg~Lzkm+;G@iRpw`JpFGgrmOeVwX%gH9<$t|@sw zS9kyOrtzvC1lZekQI-%$((Yu-NzFZAz63 z6GGW65s&FYnX*o#y|&@m6lz7JK2Y^)@p$NfRCf>Ze2eozx^7ezo9AWmzq7`rrS*A8 zuxEa5$h`AgJy-ut@!~h}EcB6jn`m)06vWPs+-_LiDr)$Mjy@ox4EDl0p58FbE_c9(}Hk&s5D!llpPX*!|i z)A!Xef9_^0o7=aCGgtjxfdmBW_Iw2k$F)FW_CEPzePip$UH6?`c(K~r7c9AGVbFq0 zjTvE5LEgXOeHg7I%-4LQ-b6^)+4Igvhpj&Nwl&sUdwM^(Rh%ll#0yQ5$G=5cn&Y@b z#v^C>8nE~ad5s~(sDGhJ&(L`9NR5{UCt)jy{koY*N!$g@$TUtw2T%>}U}OtutNsRN$SSx++-+32gCx zsLN=0)&U#!7!`lP1QS!P9^U{mtfJJorgB!$*%N>x08LGj%&_LDit?$Ncz6LHS-0Ic zGmOl;2jeySjFU9V`E;=9!)Mz?!H<}I7{>BiNsxk6`#T?u*CSz%Ou6^(8}9CaQutcw z>-l3<6%EpQ>jiWCw@-qd^>(#mb}Gos`xt+0*}*l6?kCXTb>~_Bt&8o~jPqsa3jUOX z!_(>=pPyK49W_v82V6w@xu0Hu{G0dNMxTTAf2DwH-|Fk@`&G*&tgTYXGj3o@I{dMH zMGi1+R{C#0;|k|UW6zt{%+}2mN)177;;Vj(fsx<^X0Q^ zQ?u2dWAU3%S09*BN__9rPa-4&2Lk$ zOeW1^BJ28^AmJG5LjMk>cgX~ssr2oj{FgF^wb$x73n<5_ zUrXZU+FitSy)Xi4y{WZzK&lMht4>B=+llW&Cm=JPx(MfV((5~VGJx?vhWoO1TwuO zoU^u0HO2vaS!8>ciopc3jr@@^2nrM5{+j})4d05%w zv00m5iV-&l+qV%nm^eX7#gf)=HqG-CItt2k!0;CBrp1-%o!-J~de>QHsHc%&I=W)X z!h!>aDK9SvK!7UW{TNH#C!ep!8^Ek&nzNS^vU-*Pl{`;XD;s|qjWV$SuGF86<{lD$ zS}F;6-B(dl_Gf#^OUtXzek)$hbTX4n!vB)*D!d?WN^VLRo~N8WXb5m~ zzk1BGf@__dn8C=ps;b~wFrf26GT3QA#Nlgd8?XJl|A(O z!NThjhqqc^e*Tj1-6Q?haqa~I*_|WPBKn2L_}yY=Dk8r4D$#Q*SO7>+&^r*?qYwUe z{9?eKR+}zeti;NP;qddrHi~;}O9Pt`>`Zz{lDTuL=L$z^++~m!`M&}rb4AdY{A>Dk z91y#G!2!{i!Rm2tda&v)^jdNS8xfud`GxDak>xmD{Mg=o^aCHlp~GwRD7o}k z_<_<6JZS7xPjN0e#{<<^!ybw{Rj? z{Z06WIfp@Lv;IbDDGJ3Y{OIzfX-X=D$1xfGADw#KK7DXrwk2Fe{M_7xvT-$S)eL-V zX)$F>mFnUj4UQ`*z8dh#eGf!#kJApX2iF&nQldrmGvveUu)=Vos;EmM4)yur1S|SO zkM-QuB$HH1)s@TV3=bUp=(t&MqWYJS7= z)vGDOTz3qR@8$GZD+*-`{P!yT3EMEG*IC3n6BE+JX>C7f6-z#TN z-Q4kGA^*&Yh2IfS>|>XPeqY@s`$36D$G+})MXc|2LRvJ73_K$ts#IAbL^v0M7_GYB zqV-v#P25FI0Y!A+mn+=NhExi{DHl%cGyglnEClMTIh6Yf6cPM$>BkH_4=w6z)Zuzt zbmIGEXAV4bgIZ6v*Up`#9IZ zJvgZIb5h_~J{m>#%?_UkN!#iPC~`{*Mm;}4H|iJOe1IUK8XFGjJkcWdhtO^M(4BF% zOyH%~EruiC8gFJnZ8Q3><+%gNPN7b-R&UgZ`NX~oT-QM^(0JNKuR&YEJu56fU&x#^ zhmm=2j?JGBmN|0mEF*JZcTe^c$J}13#^fK9<0Wpofa1H*s&lVF=0JMc3S)U*{Hdf#jHMW)mLfk^N}ce3ypg~AdZ-%)qB zAbbwv=-2k80eddv&VN@P>l8fOBZ8!`3`?O8vjXI6?uncT?~6vhI8k`6RUv6+>ga?R zee8D=u;fm2e>}ojY$c(BskEOrLVtw+Mqq>~hWg=<=P6njm^=WR;f6qonjwH8(TkLp zbfEVg2ZbZ#AUBR*sp6A4reWWTZS#t)$}k4?&p-h26jup8UaED`FZj z$fZKV+yCT_M$~h5^FMvJx2g}_cRd#7Fjhyn~*K67z!U@L&th{AV5f<0S=fQ#J6dXnrEFDm7qcmBQA@Q{8Rb zJyU_>1#X3X-UAiOdBM%&Oh=Zt1Vomr!}%@)@^GrSvSL+OV3_3z{Jatvy#*B=?Y^PC zPlPUR?4(h@kDU#*@vXViEGYW5b~0`hQQI1+gULW9@V8QwvN_Oe^@}mBJ7I zF@tkRba_SmLsxx_=k*Z74|Pu#{=^)o{TUj2jCuGxTiEZc=d(e8EDNIgLKHL1<}wKD z3SQ{+Mi{0Kz1qh5B^IiekI7qa-roA1UO1KlaJ%&`jI&Zv#1oK><|kV?La zvXxR@hiY}ZzyH{AuVep2W^x>_q_VMMa@6@CD7)GaZLn%Poy^_5 z1BraG8WucKKPEt_0I?Z;vh4Sr7_J&Y{{~F!l)I<;grKbDP~YUN2e_jb$}tfoAHO(k zz7b-PukG=-6i+YET0f5`Y0vD^ge(_sLtJ>)ZTrxXny95$Dy^od_ikO`$?GM#e(q#X zUS5k!YZAH2B8940#6l=v=y%U#F@(2ZLFq>7qzY^bYUBf5XY6B}B^34nR|~#yvy)!{ zEbrd}lokpM!>(!x=5xksvlZ_eyn-tbf&o=K!%=m_^1(2CPBmxJTQG|KEjK!z{1w*J zNmKDYH%y;)GQmPJ)wDm?`;FmK7y4PTR7vZ^mntCs7AFjC@w$V6L~_-E{kpia1P}UW zZzQ;A(TOVTD-dE9T%&M{woGfy8dtw$fj=mnhqD`rN*c%p6loHoBOcxji=BTu;mP`D zJK^G=Cko55p!d6#DS~o2>fp+wr7BXtI?}N<@OYsLxO&8Dh8|w#Iiua1&M^@O* z^Z45mh6W^`c7^CvLoMgY41vE2SX{thiV{dU**RB z8ecup)0CtdJzTy$*5o+@LZ^_Yo(8oVbE4sr$YE<7YR`zYN7xo0N=~Yo<+6&{pOH#T zV%F?NGhSMSZg}eYGF=V%d4HSRnXZw+?>p{Q&jivbK^FByHY@nY#he-~e~z5@L1H}C zLoE(F2)Gix?+u=axA}(14s7nTV)n7*2EI0F1AW>v72jta8{ZkiDnNST*;E)x^YqDa z`-BIWs#gaG<&wpzV)^A1InK-!Jp8K@IIn|*isse zh|S2+-QC%&?nQSqVH*-=L#Z@WnLzdQX-;;BTS*&Fs>{`A-$$<3ul)+xcJY_F@@L+P zy-+|s_5-Ua6d#LnNkL_!0vNS%RyYe)dN_9q5Xden&3#sod42#J((mIt_^%jjgO`uZ zuR3Vaq=w!4VPnwn!>*A71|5Zh1~XUFGVf{<4mZ?qe-23m|^WQqLaY&KsadoDK&Mz?4vV*pJ$IGLYChvI_bL`i|T`Mo?)}Y$Zy>pKAy)YQZp= zvVpiro%E};On4x|s9~VbQvbB{bMe3C6_TJ9_X}+16|veTx8KOxhS*T!3?L90=G{~%J}tQlx)p`8 zy>5w>kM^Oll~*09zsI=fUYUJqVt%sGZZ z>kr-;H%v>~Ty^?@sPe0aW)#QG9G!Lt@i*7IWCL$F-fmyGmq(1>f&yZl`bzYD3OKPM zd=ijUPI{MycivSNOeut|@8&<65?6kXXrNT?!1Dp+CxvicLX7%k5kt86Q0t>UI{rZ- z=>)h|&#p5Qj#NXQbR!_bEHuW#5PHU3`6TtPi(Lt`X~Z76zu<`v(HG`wzuRVJ*41%e zcb>yKvw|G|;gb5AgOC1c`v}TE#w~poBl+09cX#xr6%3PcZ2-#p%v6KzK{epeqvGVp z+R2F~h8rQl$0?=$=utI1Cb{&3*V69G$!Q;#g0AnyJKc7jFK3%@|3}`Jz+=^IaUU`h zk|{|-rIIOR9y3Lz%G6+@B4kHmVJhO_Wtj+*IIk+wa;_T$FWc89iQ6NSFny#KmDBMs>{3cLQjis z&R2hpB9;5B=!t%5PD=@HJ_|wK#CEGsFI{Q`dkAJ_XQb&K`Hoqn9qfJJD8WL`+u<=N zBPX^->9nYAtEv`l<06JVrzTvX%(TqD_neSVwn~tHOK_Ir#zm%+)`ri@UY-;(KPHo? za>n+NYj*-=u|d+|k@Z(N_MCUPSm>-n$ar7Kdm!*@GWVwRPbiRSD_-Lv`vCp=yI_A= zu)g9Ph0;Ra+GUnjErR5GLIUdIrP-*o^>5|VJSi?*P|!2WUi35KbZcZzDiO3*T65K= zk&gZ$KYgEEURf&p2ag2H=eUsU8HXHfsY$8w@XgtZ4GQr>t3qdI_ne-e@-=$>zQx=5 z6_aIB*o)MWyT>jc$^9T4nMHRnAmsM4F*G5~(O*@o>rIxY8pS+r7ETew{;$t8T-wPu{_bjSe}I@x4BF|O0-Jsarl)n{_3 z;vTVxY8nRfGCYWj8_<%421EbGKs_K(uH8CUg+h<9p}HNI24-kIq+wfbdFKC3NHfZ18BA%n6} zntjeYXrS27ytFu8_qmI{=em?rAb&xP@8R2;avcl>lS&b;K!F<-tOe1gF3R7^UZcD0@h|yVIhjayoBcRej}W) zV&>|p)b=8wbRHZdcjX&i%D)CQ__MnMZ7e z2v;`AdRa8urH^ooiwbpbZ_bOTr4i%s_X#XoZ_P#J|61#oabEvuj|qAhB4q8-IQ96B zoDAkYwfWZ~1-Y#~S0;_vRBOI$(fr^Z?Y#cxaEX(O?ml+2qZ;fMf%_ziDy8t*z)2pw5+zvRXrwSXXVzYpG8ggvb}$tkEOGUpLzE3X|gj0lb#n4Tb~b zG$A$0EwR~7t{tN9t<}`U*@ZMdtcvJuuP|l5C_AL-o6=xCag9%~)_sm!xN`PV>Es8l z4X3MWmX5BOpPv_Giz+;_dUIgo+e*(OA6-J`P}!A%*!`jc^KIhZ^=CGo94L%`)#bdo zO-cgc2_%G-DPm)|Uz z#-@Ff2S1wR2_~4*inKc0MqW(V^rlPPPTGpRs7yyy-Ki{JUYc6{vDhI6igD(-N!g?K z0+_pG7TXHAx03ucK{b#$we-{Af9 zc{jCPtGXded!mZA?`)F^6+!w;Y&%DqV17+R!AP!g9#ZAffJG|g7knP3xm#c(%B{M0 zFH%{-$lyA)`ujHBGL^PN@y&zxCF5Ml$Y=xs_wZN848|__QcQ!_pYrwB+@c@cQ z5E?v6H!AeKAJb#el_?9qbKut4t!CHfXC-&%geq<+;mwnfq31BAAWxB2EFssrfMb>q z47nLEDXDQch+YGzJ67xNKU$srLwPqnqoFyjDR_9=7x`ePspxYCKU1cQW(cx8&{VG7q#U`+_^3ea zQ}dR-8LiIKW$roi+c+83S@eYy8wMI;9yxN;j_7o*s$(`Yv<-5++xAE*MM=e~yXmP~ z;M@Lgm!6uu8x>)Xk3|^gQSLU;y)0kcylv9#@pS$L`A@Q$Y!9`ulm!_iq2yX7g4tUM zQ(yBJvpSPyD|6|2{-Q_9mP|Sfwz|6$%t(qSg5Bude58wdi^@IGI(4j&iS^v zx^N=Lt{skVCuPJAvsiBAZ^2GB>C|ed<~ea~Gd#`NpUD__mwIopYyZ0v*SYB}Ngr_z z3C0;pdf^LioKqXedwm5Yu8ME58ndI2$&{xUldL)Q_aHM&o{PaWI-Y1`K zp=S`jRtTe+(P*1g#ANfM3&9w{t&F@*wD8UyDz(mu$!0H0^Xx)i*@esH2P#v0)=1@b z%dF54px?FkStd)&b{6#8tQ{_Iq^YbE;vS9ohJ7$4Jqs}XXk>aEy__ajcx(SehUSZ* zX)5s-S|@YeikQo`rwpkWvT@#}b&yia8yTp-y>}rbaC|w6Y*qC1$dJcJpJm%l{Z8es zkinRQ=%|2>^6Osh`NnH(TJ-ppu@3fXJ`*xip#}Q$HABW&MLLJEj(xtM0cIMOo#e_* z+hoZ4Jj?!_^ot&=XNS<&Z9hw%{BdC>>Q9rI+suBEgU1tu)_tzYL8f62o=_x zoR$g7G}yzcaV7XPE8R+iwXRcQ_iAz;eO_JaJ#V*P>LKUarPvkG+}xt~2*vG<{f&Z? zLj;K;&PIpR19SJ5ts2~DqHb*9%B>GKu4 zxXV~zYWT5@6J9;(Mrp{JZglmEfgnUi6P&Iryi~xdZCi{&sq4}s4kA_@FQ=>%RUcDr zE{gpuFSx*iZIfVRG8AHWMUfK!$yu@2c;AVDCGF&8)%yjC-bn1?=sX?2p}dmIw_?TS z^YTlxOjS{;H&1E|Xqk%8vnoGtxtwxVzx&|9?2>%~@@|}>TfN_3klR}N-u$GHmC`3K ztqP^6@wIY^?borT&cJC`8p{Qx#R*9p&!!?B$~yFOd&+Y=w;$qACl^g_?K`#~`L6?C zk`u|Wp5x(O{_oR_gwgkDmTB4VJmL7FfOMJAtU|GhC>=hc?G|MsBWU@VM z!_yiKqZ!x82i;a=J6$odikyA(Zi7&_#%*JpnIqy>XIC_+WSQ4}7`%~zLO&f%6e1N9 zGles=nzP*{z4hMmZ;qbaaPByb(j$otvmPRzJ*;ca@7Wu=?UI$O`$Vftz?#kii-yNF zWM5`x-aWapH|1PQgZ759d%|1vEzkO-+OcKMT)M5Oz%L@+yD3z;3nEANMm>4%tX0*R*w!Kg%&oYB{=Uorxsd zwL{fwj_@b(C`+R64OavuN(EB84yRk-WKG>hA3&ql&CulU2naq+;Jl3 zutw+Ey%J&fz8*V?eq&5oaO|imJw~1(W%6FS-$NUntaCy+&7FC zwZ7@pA+BC$*sJ6AcGI+EAHy9{GQr)_J@XjWYOdn>xm+~Tgn3Twqr&WVPKNLoFMWeI zX-=F9?(S18=C*JcRTUi?d7>*EPSvy~_WCMz`vK?5yHx6i>W;hg7N1Ex?=;XW)*G&R z7pl-o);Rk0UTC3~isR-H#T^Y#$7Yx*aCWcya>q6Pbe*1*4r%+lG<{Zj6nMPK#I9zU z=RK==_l|xxWDGwMt;zq?%PS_-aWJzWe~8h6qMUu<=!%OXW80dm+E|{(4L23BR%_q5 zMHv)5GkLSAVetYVYr8HP_ws1}3NhE`Qoa#oW%@5IQrO-_TF(G{C+=j0XK)<90kUcXJ$llx4Dsp#0FPYI zlF5#Z$;}s72Zr`y4HB)r_e!=^;H96HDkmPkUHjTJb#Z$YzPfq)F0_7ZdNZxuu8tkojq5&q;5u5h zAgS0?Eelr1R?Sx*@cVA9@=v)QayKd~3{ zN{BU|t>v8Z^N*5!ljJ#a0DS@hg*gtM_#}xwT;{)ysnhlGAqi3L)1nu2A03huyR^%& z*CFk4`nD03&bY1%@h62AKAN)AA9*>Gcw*7EJhN}Z5n4`PqiRXKJoB7kTg21lYNjHY zG=j9J4y_!1QJySyv~reZ^xh;LcSFr+#}U^fgC8G8xNm;=oU!c4-GcTBkv?gvW9*5% zC}{4`nQx{z!qzt%Ei7_sx9D{t+mF1>uiD9H3C@(ahhMeHSLTwZt!5@4$EIdgqG!G^ zo%!-*Vk((Bw8Z7$mV;$QPv&0F^lr{K-n^dG`&F`p+$OSzCz$FCrmnSjNpW|w`Mk4Y zMm{ueYI_EX$I+V{tjR5pLPoH{ca7B0(#ln#K_d3%#?Av*Y`0m8G1MU$+!8Jr?X46P z>q<`UF3e!Yq{7Tgqb9cd{l%~*+jFx86+H4+6_p&i(Zn#>zUaRchzeXZ&rP{qa$7$Eo65TSx)st-df6} z*y2z2j5aGb*eS0w#l~d@+V>|bnNZpGH@%`|@SiTccQ1I%f2Jhei3>gB&F`=N=4In4 zV+!85tNOip*XY#u_HQ)*By=GlO8l#y>U)mXcTOs8zF7_n5-L}tm&fv9XSQH{rF^k5 z3JQu$jO2Y$TQIYcFf7|&hU^hlq0$B2=dT0Dhu>32P7W_#j~X%Ae#OtFqIBk6GDmwx zqx*Ez`dBk(^gRLA-BW2N4JpoFsz+~F@hp;&-*IzK?UPAyDXAN2okx+Yer4N;fVzs+ zxr{bdJ;slhTZ8Upp5TaL%r&^h&AL~ORlsUn8CT3s3%iqRsh~?UM4^k~Em+B*ZHHkx7h;k;0_+;0ca`5zDa%Z<-562Jx8=nBmEev{7Y& z*;>iIv1RukP4AG&WRZ9vQ+Q2#d2v_#O$jpH*!8h7k526B5ao%n>_%U^8C;%k@j|)0 zi{(hIU6j?CEoYUe4e!$!N_4OeHleroh;q^_Xei2ab0kdNRnPU|>f>K`zNS1sQGQ;; zh)$e_GwVyTGltvW-oN=BKo@Y*m&Bvg{sWmfNa0Z;-(}>ZQ>VpLKCjd9u}M zRfCv3PyI69SM+otRIf~=ytSH#j2Y4Le#44Lepy+Td5K*sv#l(Tc(PqYAMd)}{b>1` z<82x@IvzMm?wQx~myhTc<)cz` z0=9f%R&G4unX72KHJ=DkVDd4^4cGUTxPGeljHcq}{To1t-*tDXZeJ3OyZCq=Upla%& zXW=csg@GVM)|Kj3BOJ_Rzls5qAp1DuTj4(T#aC`EXMM&@N%XT;_qIz&F#Sf(C$i)b z8YLR&t3Z?Du${LfqfA`*#&aCE??bQ7Dr~t>O?O2w*y`nY z_VVGop@Ne^(qh-yB*Ue5y3N^rPRM7&-0g~|+zxm#PEBQnuSvSW&s(U=xVqj|h(>c5 zKSdWEA7W=FT~*1bZg_0|%Mr9JYJD|A#f6|!6>gsw`rae*>!_5yUi6~9plVPy*~xXW zC1mXmyzAvM2{sHtCs)KiDfZcraevSKxMa*yg6mBvhm`Bcmm_E@{?0IjR=!s;L2Hj% zN?*o%S=FPGv3$I$iI2Ubjq^g$MBV1dku|OM%T8+y z^V3v^xs5D$q(#>5(z(hYea2pU*<(Rhe%sI;#g$rQ@0g^;`XA|vbXGJsDsG~b8C}zG z(=mNL|494}HC*9RD|!{E`stIr2m5uaRu8qS8SZ^mF~51wUiHdY4jGQ?$1erB%E=|Q z@jYEl=CLcNV7)}&ohCw)s-7LKhK5AvvxoypoQnZ#(PJ^)y-UcXoG#eG!WGxepDZ$O z#?T{ravyIh?jfaC-lK8T^nSBQRrK-l)0#1g38S~IdF57$(5tkoP7HSWo~@={)oXX; z(w9#i0f8?|^vl;c(f0}UKXi~vp`^lWIjl3!?pgkk{4T~VI+M1%k6HP8mve!{rPk#6 zJBxh|^JSk$p0$+(%p5#6k##ul^L~GM{^&^>8X<}ob?WkqZWpc%iKkuf{N(04&XzPM z*%C(0IW>k-+Y}O8Q;$l!=qrmZuchETtRo%{Z8r9t=rpK z-U+E#WMb@P3`J=Un=l`ti_;xLpWREyQ?lr>mJpGtlNwh&Jyf(-Mb})RUXJ;l84wDb zLZ9nhOSUiOxP`Qrla23C{ny7XOH11m4L84|*vF{Os5PrS8_BXV_HrM8te>#%-5Rd& z{FL64hW8>|NBGf?U%d;WK0IOBtU;^s7(M-XjzOcBWB3*W`NQ;0E7td+chPOpXY^Tb z=I@+(@Q{?Q4O=Gn+nHPXo8`$_7=mjPGIa&jV)CicgS7qUgEE~N&d6|PpYpp=#faXq z&^(0RaU zw19^+w>2`M4~$mr+oz9g+75-FD}wHJEmwy|C0GL=fBZC1%15L3BH(e0en5uMY@@e+ zvjb1t{Jnu~S<3^$7MteR*Q)z$s`6M8uYMTij_t$}uzYe;k@GuI5ORNj)%A~oLw++? z&LUQd4kWS&{D;#3E})V>ceGh(W{kKZ206M z9<;V4XO5hfkxbw*c^S>lx6)cy%iYXHv2+0%i`dSN06UG;*nKM{Y&k-{s7r_DOWQsW z#5LNUW`52XNGm$fA!@MCTqE67x&PIg(i8RxUfpY2q%&@+&?>|WWELqhKK*i<)sS0^ z2Sblejm+GvE=})ZspL=SZEzt`_@k3mt)rBkDQK5@C?zgQJ+R zrIUd{HfLg}(V66qbCax3=IDyn^KKz{1jRdNHqn#zNdNn!y-Nz!)pf_qmkZJzeRc0tmq+CF>sxiDUHA@Yy4mEa970R>^C8dWEr0yXES$S>aXRAzsSThEn>Q}U1)IS+RIm{-8PAx*tpyGLc#+c-}P558T{9t z?G8R8hOu2sQG3ia@Fq(KeJ)xJt$2voaZt&NouX08>9|T`K^{%@YUn^{=&?zBW8i-M zy(=H)s}y1N=d5+yM&md{V@^DZHS~L_@oq73w-4=G{^EU#?0fBA5fbcb-dwG`c8yMN zhxmLb`JPh))k$(+9(yx%db&=(lzjV#C)sQ@rwtU z8YnGN<~nMVZwpr_Rv~UO_vlbTa1SrrDL+w_bGr+N?v75@g)^C8@?9@qm@cM`_L{ei1N3Cv5!DIvihg_SYMu)RV%3&?~r? zVZH|vVp-K!gw?G>^RQ#mecM)#NMw%OwOl&CmAq>q@j4e*k&=D^)dYRxix7GGX7=EZ zdX2bRq-MQ=mROTnEX9Y%X@|A@dL6}UyyZ1+8`ZRSj==-3srTl+-rS`&;=y94u-NXK zt=!as^P;uAig#X4*XgbOTs+I?o^1bFC|!RGK}cxb@^P|_^Z^OgxaymEhcy;=$W8ZT zsdJnW!elB;M_*nE+C)}M8-~eRrr-ZsQ&aN+(eZSH*`|XtAM8IRPmJ9wy;JqIyjMQl z{C1MTzKK;yx_ihopIkoibgOCo%C{<`6k?yJe0v1)cG1xn?GL-G^?K9!ou(H1)XI!h zxEnZQG?I=nUw?MU)x2Px3Dw;~R>4b;?;Kgj?ctn>y>(~4+F)pus$Z-7n5@rx*pQ0f z&fco**hcMPtE?)C`Q54Y(q~qLu0x;cVyLVBlxR`!A^t#f?b04r`>dLJi6!OdT?cI< z@yVdjwimM_Op4xP4%;;3J_d!xDWLbx_#`{iqTd3$1z-w()%W@wE_}(Moi*9n*D=s+ zgh{X;h`z-aTXH^*pHG1MlOju~@`bRim>+u4*84gpC4aiUiP6F4!%7O#2XC0qyDYVh zY(9ARZnVE*%;h87c3)`7e@_;#qI#BH$cjce_-owib^N#+*Y(RIid@TAi3_h6d3+~S zbp_ICQ3hvc=ZN49iOWuBOmJFp(hZ7Uh(?hke7RcBRZW7>t)i@0y&dQ34xbch%-8gY z7C7m)NBz!~7nLspS?UZ~)zMPkF>Y!O;r-~-;x%#lN^D8m>`B@UTM`}h9kwkD2gRh0 znsj%|l?NWY(V2stsjlu{71*?)Dxcy>ZK~a5b8)5f%jTQ@mN&6 z4cnGxwiOyXxR;%aN*j;wlD?=pN=9SFTd7o*MycgS_LfdYX7!m*m)h?aY$@u;`o@o0 z#BW@^f&XpG5d9<1H5?)bSswAKn!5I@~;3MBFab2b+p_p<|G~0PS zv!aTsws-KWvq^2KWI1&FM+dtSGbWNG7v;SeO$rXG=RK~@sH?M4mv?(gK`2zFX@Bv0 zZ9neQtKnk37&tSAXO2qiCH8g*C#@dtllC3Ud7Y|0+wuOcYyJEU55cjh=o_rOK?4nO z?@nZx7#|G^6Ub4f=ASRZSgR-L638xhc%E4N@GNijmS&yaT+=$aUi>t9frakQc~Xw~B}G_#-OnNYAa z(6hHL#J8-XxOmm7mJkV|SvSHZ|~l zy~!@J%g^D338#zeL-I2T>dr4=+9T8ar?SExx-@ z4kc`Xpv%)kf}PL%bbX~|rIm}HsaEw4F-`eaPOXJb8KBMEKGH$O4 zEz=^~8*~qSk-T|YSAkvqbH1|7rGBbV>lJ1DdElAZx1W)-j-GZzb4W#z>z|Ix2}x|{ zrW-^*Awyvu^vEk`n0vln*?z`Bw^f5X)k|4yUt3fhUv9;0?Q%m{xzVF29y8sYjXO)# zwe_uqK$W6&pr7Ur5v22J z&z-I&2HjV0TqYR2DVPn*Loe}KjkX&ve8|%>`Dznv5<}swmTuK<*7?$0-k2;g4R#Zc96XRa>Crff? z3>&W&3avhWX!)E!5BgG8q3%kZEnAW%5{A&{C>P#Io?Jo?ConvlmXm(vOO2lRsAc0L z%VBYx<62?4^JZ#OJdnp-s|{z?kXWVLcMk*K{53$PoqxP=Ek5+A>yUtC`7;71U*`I=tBK9^nI-C zH?MDcGRgGRoxja|`yTy)R1RG=6AG)a%LtEwRg2!imnPgQf`pE+?4re!Rt)NP>uYXj+4(PyxV(8Vw&-GTOJ1WJXVl#1 zlF|JMy{Ecu`d}=X##i0Q>d*31U)2^K=#xLC9%A$wna1xG7pt95KOoAR=)ain(bG}u zV`d+~UYN*Jbq+kZM5L>l#uF<}DCYU`hJErHtk^E|ETZsjTgdn*)h}RghMH`=yz0>JZBFN->p%L{wz&)n}I&lo(nrUq8t*B zZK5lp7*<%`X;WNLu*O7CLUn0hQJY<9uoaW@>Rr2}X}53hbe$PJ@cMC*VW?+$i|o0) zRoaiw`t6WzLeJ@SEUsAkJkKUw`ITd4tQT+e?BOqD7H<8@sP|=}V`))47(YDHn`*aE zv<2ge5(*Jg$6B_Kb&2zaDp#-Tr)0NyBI`SdEYN}WXNPY4-!|X+?(Ns3i#o^1ZS2kpv8t1o-qT@m?W1>7l9t5R<-9t}sf8)AyyJZvao4tO?f{3p9BtmAk^+Ufx`G{7Aj@(e;lU;;KIK(zF=o z+1)X}e#=epDQafAK_f@hdA?$V+v+>cGV&u6v^R(9BrXJWuL$wyM8)j>mR52zHT49U^nnz&?Cf-~K2*R+C+wmCWEmyD+^%>qpzk z2Cmd+b6!R7MLeDKS(oEuqPkM?yXLj%rfI)q@K&QoJ{=`$QWpekr7QhQi%UMQ{V@HN zC+S8nwa##Q{A-D8A{%|}f_!huM_s`E?^uWiu(1*3hgD+hB5tL;BJa}GEoUgI7V*uh z(V%Sdl#DH1?WPy(ENL41iWVy~ziupaerJ|y`hNeHBKa4y%L?j8vsvVZo<)?gKD!)} zWsU8QD&y0tRykl(EIT(5DIT*-@Zmk58;6xyH%10muI$dmwyRQHOl{+fADKDOi5`Hx zU$>Eep*7C4G-xu1i3hpi1tX&a-j4cbM#7)CosCKTGB!AW*)t|JW@Y`2yX0wSr!DU% z1!@%~*sf_z?dZ-dN$hmkL~XXNQCYxF_+rJu_BY1Mg3d`1?pbk$BCywt^KScB8sGl< zJTlw*!0AO33ElK9!jpGn2HgnPK8bTH_b*o$py#6*qFmEw9D3_?sj1juQ5N-+`vfvm zD5jb=;I`r_H0Rvg^72aM)gC^pQmM`$ZXLDBm%!zq{BYIl z#(D8Ovv%Gz6<*smnV0R9(%I)yf7b6{)B)3L%XGY4E7@zGkUMfeON?oG#CF`^93St4 z73v=y-(C#lif`J^IW>_nGe29pNd5}Lhr-A3o*3?iF6w1-Z*?oxo8)qy^@&V=;y67- z9{6z9(-51KexGiTdF084w^w3qzLs~yt9>oM_3YS1x3u+T92>B_&XF#b=gJ9cHKNfA zPo5avHoq=B=yp3R+u{1~-Qx#OzcPt;q*`y^ucPB$cyM{zX0c`DWrG-{f&4r3(f|ft zLbAJoU?Kas6|j)!gqJ?b&Ap*|$9rZ;ob=!;>Ie=eOq&E_q+dv?Bfb&qCO$N1P% zN5gEU`?}-)3r!)^OiL}EJqiN67F?|sto3n^{rgH&nS`XKIj;LD>aA*Lt8N-7-b_#* zDWX`&?9Dt7-obh@U%-}fT{)|p>@6BA)monF{IJVboDT*E2eS^{zI(ZOFkx56{%4+x z_qfV$@Vc?BKW=qZ_<5eopZ->1p2+hh>vTgJ_p9?c_@CyE^kz;#X27o1262{lkH02Fl217u4$M+wOic>rB1X z!%@TccI-)aW(KR9nWPn?czs$(@;s|^{l?=d`J9VplauY6hf&M7aic$p+t?2{%vrT< z{&+rv&7o_?Of))9S^MijI=Z&4v^KF-iD&19J|76Md+@1a+X>mP!O`vQ4coZTjV2EM z34RkkW8F@Kw^zpW`~uIVrWiBa5>`l|Ulg&FH^Hj>2R^@{cj);dFnBECgahrQgUVPc z`l7aU$`*n}&qV&#$l}ql;tj*{9J3aEv*PkyR}Q;R z?(eI*Vndeo_Va|l{MstU0i1d`+FI>GgIeo4EJ5d}7&QKF_FZyu`NC<^|g}RsR2K<-b_Ch-<9sR+lre z8|_0MtTAzW&$`QTk$I;LzQX7z&SK(;uiWp4v)Z1-+3dn_R!aiD!9N)nIhlnsX4| zMalR+H4BG00?mtPB_bL`%MkrX8^|w*j@=jFwfxy4A|Au+2K?0Hk3Vo(+R(GD`F82rUeT9#R1pNVh0kTE6W`iLDtAGg9bsZvB zL?Bxfi2hWcthWhiVbQc$Vskh}j8vEG!47;}$SMICT*1 zK(rmv7DQ_iK|AOX{mX6Bp;Nb3?)SyzVs8?0=x074@)7#pxu%cEJO7psc;&lkB7Tq& z#kgCzcz7-m<9ff#L>*wY4kqdai@7(>V(d=T6W9m*O7XXea-)`1Mr^bC#d2a9blmHW z5x|{@v=FHvl0_tj2u$c2M4;p7onL?47c2Mq5P1wT0=zy{^%_4~_XhWA{(u8+kEUT9 z!vnDJLSZQ?!Uk?LfQVw#-)(MBW0AfmhH6Afup*2a28$&jE%SBtIa-pqHQn zd#*mjLDm2(q+oYQdH^Y0hkVeVzys(5AZRb>2k05XzZ;k)xIa3ETN2y_D4@M8nMf^C5ML0G?Eqpy1o*+e z{@4IJ$T^AMps%32&<2nj&}Fbipv%BR9*+c~{f03Obadm16dcAS7{|aSg8c-01M&|2 z1Lc9e-5Q*MWF~^xHn?vS;R?|2=c@6j}5Q`Mj)`4 z&<@bIgT)<0IkGG3BAy5P4>Aq93i3@NkbM|$q5psvz;BR2=u0TW^Wl49nUEjGXy}8L z2Ty$SLxg2X<1UO>|7e4@0KvEnc}Q(VyWcjz4e}1U3iSf7pl*`=2fl+GJ^3_C>?hzU z;DvhtAK)h82i*pY3P?5}C5_)C-6pjG`e!TZFQ$#+U@Jj>KtF-MfDf>eaHHKH8|fTe z|FHoMzyP>`*T8?Up&&zGn}F{ycC{h>g?5o_B#cFX6J!Q-mZ%5F?*v`=c}##dfcyjB zLH!2S2Gx*dXH(;Xxzuehke5I&7 z*cQMI_7ZFl*i7(C!RCW(fewS*fNlWafnfi~Mv{NvH(&%m4Qwjt9kdC?HAs_RjuT}c z^bq(71a=X|QIHkT3m8|yz5>Bm0euT?2iXK03vFXD^(2nl>%7oU#J+8yk6_!u{s8|0 zJM4qaA=x9aIgk(J>vy^W@(*^NL?A=JGmsYB2R(WfDdp2!FUTclhg({2D|z@{D2$!00=OH z{f9O|y&yXvLm>aJ#^;Fb0UZZ?Bm#Q_IziF}kQ?ZmZ4pABf9e}V$w zh&+LI!2FTbD(El457+@G;Dx>bdjstNnE}k8x1hsdOJJ-8{R3YO`U3a}ctAeDj{v&~ z#H49~!~7F`A&5)BK8y)qr=U+jKEV(975@IKJb)c=llp!5%RF(c0?gp+0v@mzprfE0 z;NJjd;4QQP>?g=Hj8m`==a(z)!J!<`10sHd!$i9YeZs6`hsvtLjnTOCudw~fb-*+> zyFiqA@CN`3;01nx9|?0Tp`a^7-hur9zYOd=X&eT73jP7uEVu@~8N^t+#^#890{CH$ zw>cnvPAo9}sfbH7_>h0u20lN#=m3#lHJb)kS2i}8SWJ6>9pTQ4f71#s74{<7(>;6^Pex)4t z!>5UM4#p?2O~jbipW(knAkpT2(+3n=`CsElb`ESb*lQRUpg;Z$|3Uu2E(3nBnQX{D z{0iUxsyt99^gq~3@In7HekA`e-huoO{i8$C|8xA{`+!dmcKzSM556?uCypimWBvnP z@QVPy8=6c0JNRKP591!px8VN2N;ZC_92jpvZeY#<{@b6%kM4&t8tgy#+u&ROO1*zo z9#&*Oz{dyq2mj*F;}0h4KJXr55}?n26}Dd~2kbpyhVcvh<2CN*|CIfKISi~*z_ z@H1hKE8v&>OBle%gYg%9K#)J^!%aSy-u+eBex)3_(Ckal2WZWcIG=@i7082hMBa;k zcE4EowMCE>23dXL90ul-;JZP2|Lng1#x*XNb4%cB(o1R)ePrkZ@SQjMCVx>ql}q$B zponV28uE>zrt#5p63-#o|S=KdS_{#BU@VL5RiL&P>nX%l14u%-uN68Hn` z$fx0SIJE?G2gnEW21fM*IK|4<#CZ?IVxTXeoPSlv$ zv)@x3tpY&#fbXBA%f4S<3uzxlLrfQ#X8*e>^*FKoB{G5%)Qk8=Own#29ODE88`5gB zZ|OMow-o(_^Ma^dyoi(${di7`86Er^+t#C}qc$IoyoR2;`pBVU`-MftWPyI0I=)=l z1g8^IgRxol-V@Vj*-bo{$b)Gc-czgpUPMKX5=y59V~RJ_Q6A01L#)z&8ZH1m;YnegOVMTVc%~V&o79fnyl=zqj8Nm9L3N z1(6IQ((?yAXdn6n*1UgUfP29&0PLhSYv2K_1%Q7FyoWh2#B)i{I1qhS6r+ZGa2>{L z(!7#eUdI`guZ#%Vz7-KaqSc7tSqIXy1h8&IVFLbs@XM^^F9D;t5*7`~PfI+!dcfLKR z19AuZAXo5g1?hPxkO62j9E0x)eGUB%u^f;UxDI%Lj$XV0Z3X@N!DF-!8?+bBfgHkh zNHJ(5@SpTt4Ac*L1#xDO1DIz4Z-CFxKhR$2Gr$7v1=$B*17sEWByDqC4iyU+zz#q= zNper*H#&wCbdso-Fo%V@!Pf%bLwpn34)v4x5AqE*2x2y*cEUca@j=~Si$G2R&(^(; zx~ObecLo~(>(C%`z<1~a=y$+F!i0hC0QracC=iqZ{Q&E2(9XYI4}o(aFCee5eg?P! zALt|a>UzFspl+xSWDN-7%RfJ(@-t5`Si=H20=@%5{m`$lzC?Ns0%BIsN6-f#=g?-5 zd9aai4R{YRVZf2m_6FA1Vf)+uCiOY+ozxc?zt2VD8X;*d5$q0Wo$zP=!?Q5Jb7&*z z0mN`XHefCbeFE13`%m=~LHx5nt~cALp zumaEE9LPWP1=w!D^=In`-a(mAH|d!U5*9cQ^?*D;KZ892Sq026MiJLP&>9Y`m%(+& zm(~8}m)DVw6}D1C|3Q1d^jvfcS2Rp=p+W$xS{_Oe9 z?&n{@+CKCttRstfoWJ_FWxzRzV}tF5HG~cB=imQro`3fk^{W}Iaey5J-lEtpF618H zCgy%t2MG2d1`n}Bk{<&1{JZu2qx-h{UU~ug2Q~m?5$b`sF%Z~AuzL_2f$?{%&xNP| zsEq&g+!pT(ub>Y=zrn`Dw!I_HH6YIV?K!AZsP2oM|7kt{?0)H>D;evKUswYF3+xie z1&lddhfgm`2d0GovwQzvxrP&{@dXq{7{@Rr0`ip+ks-oURh69c6>KTIpN-V8Yj1N-{sTrIEQb`@4^+4-%85+kJA72 zeq%xs!v79G5c2zav`$^cC2sZO`vQ{wRsCH@8V2wqH=A(J3kA4e;x*hXt^k*~`3h%F zet{!=UH=F-=^V=M2yHlAhklRI{1!i4+k@*BJ|W!;V9OU(rAehW$)^X!Z{@zV`c%97Zs#?crD@Ogzsba^CIZ?qPRC*vQV^ z#na8k&i%)pk)4&TotqHv5qBFGH)khnAzouUH+LtOqYC1}qVP|MSIyJe!_&=9;i#Rb zhntnN5U+u!wX>6rj-AgQm&0~P6|A>!x01AxloFHKCSfNkEyMr!m3bcZa5`c~s(rVe z2WeIe0PVl$-{EHE<#g0RSlh-?$wrrWdA}VGqnjAfM2(sG+p!>O#1~o=b3{Q$G8FO2MH2%a z6oBL9{eFysK=mjPh_Vx}JEF<*QNC}r!Vst(hCWobk#s*Vmb)IUj1-XWN5|;Ch7QvG zyqF^zE?wS!3;CleF-t^%6E?yh45jD_@jpf&z#by>4^E*!)z#JL46-0#M9^9SF+qQc z%MI}7|Ncf(O85sLsH37HO8@RWO;m(eL}^sS@9&^Nc_X|_OG~4EK2H--8c|hR5{|O} zl%FOdDr!C|0+oZxk0>P7fHGG_M9r2~d86w;<)=Ys(dmfNaQBGP(%Ikgqq9)Zd<4Lm z{ZTIsI*x#?#2b}A|J(V}swmb56H!%Fh1wex?hW_-mLHW286zS>U}qfrzA;73&!ZO1mX<>PAK5V)l#5t= zL^#Uv(|Od``B{Vq;g9%@Z76>XLJw{5Lx6wIkFujHrQxC85%WK)C6vXnH&T#0JO@6-R_~dV5#>+>I#zENXM9m$zfo@5+z)R#HR+P1SE~#!!1_ zW1!-QVbkB2AA^`b3!NtTbAG@x`>iC?pV*8sMW9j;mCnWp{?zRVKfsBIn2nkBuKJm8 z2>vX3yVPt9Eqjz3kz7KC|w$Na<}CR9GkTU8Z~`0!IXh(A@c zRaK}HykhX5$|2@QEtsA4ikSVW92(TQ-|~AS0sXCBrYIa;KvyERN8#UP1QL`VT|njk z*0sc|(C;xZzuiwfiT*G}M38oWDTQ(9yDj<`>C)P7`TD*sMK57!(t%7`-?tPksS=O- zzNdu0K1FM?U|X^OS5l>KcoEwGH>@b5Gz1dh+xJuu^%5^4WkjTL=G#IFI`MZKfyjXW z;W!iiJ5x^+6&@A!V^9D?jjWwF0);lB0WSq(Pdug}+UF=_mFB-4BfE@*J3ONNoAS^g zbB_uLmnL0D);ubr$~)@2ZKgp6foM&mzU5~E<2{dzVpJ5=MzmvK>ZQNSJF*urs-Ww{ z>b_k^X3?8;jIN`15QUR$9@1MV-`l(Ndw#HTQ8V6t-*pwPBe-7P-xUw+7y2Lmqda7T zpoky&QC-Nq&3b=>3wl^J8!?M}e``L`K7pAgb7n-mh)8lyK>PoABmCQPzHA$D!XgX_kn<-z9Fy|NXI{a?u6iwpvIMlaZ9h6PRZk&=ls4Qm;pdo{nQ4ozs~A6Lh}&3+DBD2J`Jf z$9*$cK;JADbSegm4G+O$Bf_wh_-HI7CLRktmxx6trC{gIox{#vOu??54Z$)J&R~V- zqp+KoBeC+-2rTPjJeGGk7E4RHh!v;AVMVD4*zJ^fEIaKomUkr?yOWlHm1kYTqLQ<) zh|9THR9Y^Un4X1Q$h?Z3%e{e}zg~i!zIhKzE-b-vbN&x|?->@=vaJgj86*iPsGul0 zNKzzAP!Y)zlq5-sHV6nvPLdQPNX{TpB}vXSK{8F0MoCQ$HW`}Sa3`+4_Fil6wa&TU zcklDuKc{$#S=Hkmqej*2*;VhTIlD8#htCDzb6zeeDkuaW3QIw5MHOgBjR1|GW5CzE zM9@`~1O`e|L3=?u=q^tOJ(U@tz4$Xg)O>=zvNsJNYcs(hRBos)1<7CGV5Bh@w0*4y z-H0jcf7Ao}Zf5Z5sZ5(7T4ZQAM2R;Lvz#lp{0pB)3 z@X#jk9oYsUqZkk}aRefe8zB7q7Kr}73Bo7VLG<`Ki1@w@+1LiLV;GP$wguj!jzGr1 zEXW?;1nJOu&6>b~k0=ayH;nUe|H$z`9vfhDBP|56{7iXlp4Q0cyFXheM>>{ zu8g=?OwxY^?=LPaR4h@s8E0lMrKosUQYJg=Z<`pZ{8Ca<(%RapqQa?d!6T)jaQC(! zV`9c%*+eZzOk~q?f3LcfzRey>H|gPyTZ9! zoqvI^@9FA7Algq=T7Nb1;?<*TV#>;Qg*vc*jW0vABier{oa(d+d@y<`(F)n`#CH6p z{W8R9`b`09g6pxlpmeLsDgLkQH}?F7|6QXk9A!c)_Fv+AdQR>C-Ug5Ag>}kP0ow9wH20hc2@WPr~mz<@WGzZe>H&+ zOfd{AY(I8UP4C`aAxYQ;}{~+=Wm-TE6^+H>dcn!Bd67(=MF)6ccNtDhA;Z zh5uaf|FNB+(XP=^NZ}NJn%ZMtKEHmqy&W-FSoKHT@8#d{qk~X7g(F%WO?56Zb+sdY z{GI)7$o@a^J>m3p50_|K5Qvq+j^Azm@i;Vo>d!wl zAJH?o@#Qa{l{mFO{!fL`9v2T6r`NbWJ>wh2U4QK7?_~&oiat%JEg-z!`g**>gYav` zh~F`PJR--t$HsnZ;8X+gcINHdX~JLj{|4Xn8~n6^vC+YRc_UG&kt*XpeGmaDBhB=Z}8>UPexw;(v#ajUoIo zhdXBnM^_L21`qZ3H-+CC81tqeUgQ`Z{X6^L$9qoUP&(}flw8y=O=|RvZv34;|FHj? z#@P6%i!YtN?)L-ie*J&t|L+ZqkN=#aFfd!*SfBVC{2%N?4oyr<%rQ8y_YL%QcCY?E zCVxC4|LOl}6HxkQN6ix2kNit8q==k2{p$GBG%-F5rID3CTKmuP$SLsq1abno@^>cx zq=ZC{{B7HR0{;K2{KjPe6-W8|`v1hOev3o>Z^zA~e#0|DLwd?nPe=B@i(CDJr{e$N zT>gQlYAf6WwyH9~?wJ9weEuA`TAKo6OIz^N)(u2j>j8g9E0FBt0%G5If%4Fo0OtM% z*m(s3OP^3+>K6l?-n<89F&}{il+ELF0W2XGc*f@dr=(n9lU4-mGs}TnMhWo9tpU%A z5Wu6V2k3U9fH49ER1u57{51EhfmdB~z#ig~E{GNI?AtOhg)$6z$|+ZY9h9B>(7+Dj zl&}85D_=o;(xq<`c=T@qcZjFB4{Za7@0j2C^+Epa!7at2#bjW@1bLKObm#MjR#Tj@gOE438cUE0hKWUpe!K-WTYg4y0o_d z{^<=!O!)xbWaNU>v@{TzRRA(`3qT#j0W0!8fzI4$FjSrh5GC2*M@=D^hZlqCwoEYB zRszsnrC=IS2fQJk_ol8F_|*@954EkpuVD!IHhu^1TfT$x<~C6IwF6|e_Jho}Zy={@ z7!-C4f=@l80N&LP@&{3%tnUXX{x%NYARu1Xiw1$i5Vu1vgEvStcn9S-{mUTW`!et! zUj=WW&y9DZs~~i26~y$NQK7J2jX~sgPS1m+ZG5K+5#a+i1(q^K>##% zeq%cze0U2)LLBdu-^D=uE^=ZAM57?i264LNv2E~qbPl9J=OS}t4HSK!0p;V1-~%Mf zhWMV}eW!WYWoC?_jiKk{$bEG z^aHef8v#>2tzc&s1zNsOf>zW#_&zlQzRqugMyRdEgegI+t>+JJcGF2EcegM;G}aC~~<{~x4Z9~}P& z`v2cmt?3w8xtT5hTG7*%RYu{GAk$SQn|}w4hC6x*2nY$8+`TBsdqwG`*&hMn9=^W* z{;_d!5~6B%^+kCZb^a)?3k^<5iA#$+O`@iEF9`9nt-P}Mmwss3=d{z5k`Nact1Nw4 z6p}kX|Cc&R|B1wiurG$XlZ zSp|RAKb5zhBJ%S;8KCXvLVSNtE_ukXw5?CgXfkQXBhPsrm| z{;Uu0D}dyufX>z*%kz|wJob0UkxdYT%#r z$NCCR`O+^$*khbC9;=}-f42YWmmEU$pphin)~msPmiHI@l21<0&dv_serQ}0JoZQZ zu|BBzo}T``4tQy&@Q&wsi5hjq#eZB1ZcWDWw%j6uA!Js8ZA2jf-xz%2DEkk04?_p-Zz{HGqElGhJ3 z3I~Bs2@)7q`~aruExc02(+zbDm=_w9Xh^2aaPKz4fh2<%${k*BfKfq5u~x(mFgwm`ttCN!6BL-QvF1k7%OH_&Tu=C(oL z;tqHV%_$+!F$9W*hA%+#_RW4f~1WDkP5{( zYZjn6a0v_2pn4iq&%_*ok2^;o2a0`uhI0Ns78F5qQYkbiRYLR6Dikwa{W%SmmzTlG zJ{p>fev5bh#oOwCUizOA_`fy+(B~7hf%>mRbo#&@v7)RL2Zz9QAr9h87oiuuYQC z85kJoKjp>Ok@!^?|CMf2(~66qivKYgjQ70&3Mr7ZaF6{*SX}e{_sHUik6LI#w&Kk4#~^|N(LC- z(po1xW$8-9!-Qht{E0mD6MqpKv+I5-Sfg~;x0$-M^h49yR4&3#S3+Tt^RIp6kP zDJZ?Nw{?old?|i@dwT*~?q*}XkaVQhb^DRy&-&eJlm~PCZlI?JOceIW!wZGlPbQBk zj>@`js`hfBEY@qj2gWCLARqgTQ&C4j<0}&ld~2lZq)zzz!L9SE4?FJR7J@b0*iDp{ zx0A5J-sUP(R}rM#!b|!Hh}+cW`8E(#gb_ccnm8LGEq+DpN~DTS#^+h>4~g({45?yVo}A z(n?oO7BEpx$aUdqMx>QB$!kO*_dF@97oJQV@L94u%jb%e&}QBXa2s=3nN#dO*NkpR zY#62IbKjp&|5+N9b(G6SssV2Hdv~4)UhN>G#IayN$vS9l4&;3p)DIWX^-<7ps17{C z9HnGiDqVTGHrje!ER5-Eh64K{%RR-nL3dYccQ$$B)%PfF5^Sutk{Wv2Z#e3Asvlc) z;GXv`XMpu_NeSsO`rj&)&LRFl^ie0beiXcuMJ1M;7I`+FZSqwkdeX7i_iSpvuE+f) z;>`Ow)aR8eu|KaZb%-Zt`-9xB zG&$PV;qWpyAl%9BWJI2gZne1hVc=|XKsyU=8(sw-ccMj`8}WxLcUYw|GVdw+t2})H zKiG`wu6S6)AY^#7iDo}|aBBSl?E?N+za8Ub^7}L&Hrb!=o;#UJy}u=8JGM0Ni&KrmOCvPr@gp!!+)J^op7Bt z{%NH{q3Y=s6P0v_CaveVX%i+clo2=la~C~HH-sLENDY-?DKYcw^zx_NBkpY`N7@pN zN{8RNt@&D|xm))^+ehah^&r7Z%(arC!_7;1-p!)Ky`uPr4{yk3$@eFPH*o8s8Huk= z3?)=Z!z(cHh9|EMOY}O`X}N>7fa7b)7ba@rQsv)x0%F|z(rB)B^kjW_=SSHjS1DNl z58^JD!LLeXLSV@>G;hdc(P)xcmf{tJ%{ZhDw=uq`OqgZ$bADSKe3LhU#!O>cxp?Aj zg)nqxlHES8tH-=F(Xkbtyv+=6J+OW0ON+QMl;?j(XYr_#!#C7^&O3{9in*4eK)7ke z+I+Y#ekfc;t>fJJu=gDoF6Oke+<}GIiisRwMI+8G(cBSHwOBDhgo)f|r8ynF%Vzd$ zXHuJM68Sv$S7=->DDDfyYP`g~^irD?tl}M&+m^#Z?ebv8K@sBGiF9Ho=c`)MXwoj+ z57%nl=&0tvOX@kJ;)K^rvRTRb@xpo4@Qn-c3~AGGg7ImQ_*0Hlo^;a3IfV zH$%DD7Rmk7tm`OwI%Q_xFow@F|=n6UK{yX#}C8GJ8133XD^SciZd?2h`!2CVoN8nm6Vi zBa=9?jkK-@=F@p$)3P=d_qFcP{=|!W8{(nb^vOy45~c{hEyR#UIp4Am$!b|O@v3XF z;9JPVnRq=wBS_KCWW$d3KP!VAoJ?(O3B1LwMJAwYIzv6+%y>TJ{UC{&glv{TfpEiy zN74kbS0zE{p@c|pj@=st=7=R6E|RKE1RPs5@Kc|BtzEN@DcV(>Y|tt7unLYf&TrZs zpVaGQXC~doSrkoeNpG})-DeO`)vI{c(Y|&4bu zTCAu(`ynY$>yAUihMgJd{hrrv6ap1C3?`qNoznY2$6WK|48~-+OfMQmL8oj;Jhw?IpGokJl*t;&T5_c-S~v zpO4e-gvZV2{9W`BK{+sEu7$Gn&*u=C4zih_nBJ-Hv~fD^R4=RaoVAjW=^bUB7&R|} zw;it4b>$Z|q-Kvz#BSTHe6io|sIQbQr0-)S+o;j6J?2UtvL|lyIOD9q*58|J z67-JkBg-t38*Ue(bg}l%yuGt2`lce$EIUsQKShJFS^Y#X1A&pyFGX4qSaOkM#EoM~h6_=%`>A`B7s!OUK83Jr zyqKu$@!AkRq1A2F2U9Px1x@7VV3bya7p>F8!h?vTzp@P42?a9AZ@iXNnVfk=grC8~ zAS^<3BzjTxBWz2Asg`Nk!mA=iEFz#ruqqa8C6f%~#j9@Xnbbon8xzg1m zc6^-Icj|rtgWw>)iI;@2jaPSMnADw$L0MRcI`uH-P4sj6Av`b zfd?gu&N-z?HiAtmnbHa<$2UlJ=J@`_5{_0q7`ati&Ofvj9LuyY? zoKe3H+sbY8s1+LCG0Dl|$bf8PKP6UU1}a$r z`3Q24DK1CJ6!uReOG#FjaQBi7+cZ*oKS{xyS~UJLZ}$RPcw;rf%^Fs#kVkl}&qZrk9= z-tcj&jYmHA!}U2&Qy*nuZC-y!n-~axbs{nuct-p4)Pm_FJO|~xSjU31r93Ol-cnMW zm)**N*%qrXHd_6wd}pIf`^53NibEE9^OV_XJjy6nOPe*2bzUurpZspN8h%4-D`Col zovp2O#c0cxgezVue9s0;W*4yevcPNFa{CxGvs)on{-Dpl#bmpSM$uym!vxhW$|N^D(XchGA+xx(vk?I_>y$R55U z?1|nTVeC;~l~bvroAhMx3B-}2w12X$H@YInY2I&Y{<;d;Dm=)|;6c8Sj>r}+xK&Nk zU0qsqysQmVPEcTr46hMCoRn#ew!Z0(V2aYEby*t z-4zAS1FU47L72GH?%uK9n!On;*=uFNGl))V>l_>tR{5e>Y7@J_{dVnQ&&AsRwz#tCrPbs zj5&ANx0V-aqTC4TKVlIi?DL{Wp?Jq5)-Z`f%&T0v*ooce@$;p-+!fXoZPghzF{<%? z$jnbqsqZhZDihC~zjE*`R$-kxi=!3B@Q(c*J5BarI7jH)=}e_&NByXQIlHI_(=5j3 zPN}=R9)2@bN1cVo)bRB#uarV}o>?dO%S3L*@uxOUsY`-)*f@2wOtvm>a(;Wx7(XGy zruDu*FmsAhZOPiNLct3?=y2cM<*11C_T&%vmax}Ute!!G`l^Pc&v~DpD<1TfXq9G{ zmzt{Z#*g_ci%dyBD!lO5wVn`XKYKWQL>e%d_Th<=bVbDq{h92>gPUp!R5>IwcI_tA zcE|4xO-#Sbar&!Y$~ylxsFdLQ3czf=M5ai*TG z`tfZ6U9rj^6mZ%b+{lh76gJuBM#}0Y-LcYRak=e9{3`{yRCi{B_)nxAHm>7yjmvi7 z`H81j?C?*mgdOE0-d8)it!*_(6~KM6#^6bJgeS2HSo_t>qL%b~)=P{}skFa}Jpml- zc(=Z|5Tkp^&4aV^Wy&6BstY8yF0X~z)uc`@|0v0{3_`|h@XNDWCJZbQvg~8he@u!| zsB^83RUu4nOidc4c9=9lKUz$0#h()3oDwYEx3mY{D9}vx+H0*4o9Mn)W3#y9sO*ph}KoWipt1f^6>HhShb{-<&l3mJ0+2mUTDkY{>3 zsSJoIA_~ZTFv0sbiH@S5Go?TON z@@gbyL7s5psiGxn*-bA#e0X(@Fuq?vhKxT^>pY z&Rx!64d||1oF)lNOA3ZFu6hz?&LZcIFnT=F_a3@ehX|JaSdAaI@;W1Dd`ugO5*vQ{ zN@h;qYtWKRcV_?glVR3(Pn$%{F5UN2+sTb?-FhO?%YE`>7?J14a*gb61PfSNRF+o>@s0TDRH!z7u-KobCFf_LX&)z`=_3FfrXA*DUM1FI=Pq2=*mW@6<^R!k4 z=>Tq9dH5+-@#)0jav0|R5H`3nJi5okr(lp2G1tndgp*8hpCy&xs4p-C%V8c;RXqF)MNM6Fu3;&v1IM^%Z2$XheR3?932Cn zy-|4qon0v?dj^I!9PPy2sF;^)FV850ehKSIL(Sf>q*W^IlgdfHz=g-muH_SsPLq&0V*pCmVv=hFT}3AEVf}#<(e3uZ5H2q}-<>8sr?bBs}gAyoZy5p01)u zS(u(}h#Zjg(^F7RV$pFjW-wP^lYbC#E?@AFh$hADnA4rF!4Xfg^7_R!)wlow%ZbE? z`EQmeLFpaX+ZpFK%XQlnZn}z9!lI^((xgUV$@l%Krye3xV`J0A6bhH{^NOSSi-j3H zOa=SjsAa43l@H-tR3V?Q(wlNDN7n9z;@uIsC*MA?N>P9=_To1dOXl=}eB*rdTJo@q z`eA1QP>;q?-&4Djl*uBmkYI+qlMp5%VgDlXg;TqQsV_{p=3N_2lL)J_M#7}9s(DZY zf3Z7ECgvroSeg-(*0fJ8PSTaZne0B6IEbTr@!;{9AKe`vA%!Duo|nBl6*nn-mak!= zZusf7bGt8z^lvE*&K9;JiE%>FlZU(oq>R`_JU`oqy7v4eB+YRf4xNq83EV*Ki#6w` zsFHKsG5+0&wDIzMkC0>G3en2`LuFJM{g+^9v|q;?LHV~cwImOJ^3ojnpEu$vU%n`^ z+eD)%8gadk$cQ3H0At?>_Q!_;k$Dwpa=BDm<=UrB z#q)9;jb56_z-*c_!q9Y%==<4kBE-Sm{$UVn*>o@VFR91c4FN}8{WG!~8-tGwKKvh}< zi)aO32>RG_up^<&+-!fjI@xxfunX`RM4oeQz+pf0{e6J~34zREWJ>%Y!t)HJV>NDkEOnX~A)SX7M6BIFMQU|Pi zVVuyCR*-tVz2N9s5Q5J3!FPqjaRF_^3r4v)sfLB$a$GI2nq?Qi(KaEGHYKh~Uwe_X z{A)vst6~)6FB*O-q~@XDwWjHL>_6uLZU7{|{?-JIe@^Y_DV+ok8*`Is1@!hCK6mxKc}S^mwMO(mCpR z?AHnW6RUCQl6)JYlRS%?TO(Aj8@4V`)L7YsirAZ-|HkXJUWPL3TlrE{9iam*L8H^b z^O_^H%MmZ2`8;xXxY7=LN!Vs=5*dPi5YJDZb5HGF1WP=DkvDu4y^blYe}9W+I?8~r zky654Y7Ge^fa@&$_@PeAo>MD4X>9GGI12Aa889%keCF3?G|MwIxT%9u8YDb&HGST! zyO4m(qmFEG&3GItc7bB!;^K0@OG?`4#>EiVB<08PO3VfNhv8ZVSPIqK8&y+U#s^$D$6CZMG1Fb+U!x zlSW>tIgF!OC_UzN{joE19~B-s$ig0%E)9wZrrk~2{xQN(1ecmiW^@lu zJ#JFnS{_uzJu54~wL8iE=}m-RhhXODiogXjm&vJx@84_N=NRkcMUvB>y`3S(MKP~B z$ymHvUEUl*9g8t~Iry>!OxZTkP#T(<4m~sN`!Kp;r_a7i^-Tx9lc!+VNPQF>)uK$u z#iK^wi9j6`@f6L>KG6_4j}(TUm^dhZwU>8xm)sLJgVf~R(uQ9t$Nwgks9Nx|*I^^JM*p*=O z>2>H^s1rub_%a&I8#%ompfDFA==J(}Y22rIXZ}reG_TC$9BqT~B;V)Eg+g9<)M1Rq z#6^oMeLNfqXcFoewaK!4=kC4N-I3ni;B*t zGy8-?%a&8h)TgHWs#)E_8=f4!g76oj^s+;YVJku~h$qh{E69Hqy=GL@|GC82dJsb$ z4aFCrJB;3kpN-e(Ll6-;x-s*nj2pomS?PP|TQU`xvUuAL&0#qA85oFP?XFI`tZmKa zNChr5F&9ja+SDpD$SzM*b&ZcYt=EBk4IyE6GCA%fDR|?43Ct>QcL^gQ(PoVtzFxw+ zS~h0b`L+u;5tO|6z{PK+3~n-&&A+5y=cyx&F55Z7JRrD>*nS6-!-bQmC(_lo+%z;i zsG+VU^w02yOYTYw`WW)vxhx&pCo*vcoq;1C@gH ze71GRj5Z@qcFvq{_#%11t8cDsKh6plKOmcAT%D3)LN}9{jC7A8w?95IqSy;-J;-Lu zyA^P2QFPKK;rov&B$v%)0)F`W2(zC-Uamj+N%@eAHJaDFw;?|NR?myV;-ZNh6nfH)qUjSF9a9{mU`=u~ z7_PBOn8fVJWUWnptKrsWylkoXez($U%dGI$ZTutC?_%`m?B2eSIxR2aYW3~xDns&T zcyQzyWudzd=b4Wm6W&hez$Nin%P4K#>b&TjsUQ%qWXlj}TimhuW&osko~I3$&z;g^(4#UOQDo%EwIk2ShrgTJp1J*JD@4_c4|#!aXo; z^Ap#41n!4N0zHNqnQZGG10pT5{EJRLR=5u*-M-2QEl82w^*ihSGoEhoRZU*#W5`v5 z!mja}n!J#JOtsg@Gn^U$&5~FH>9$?F+eA|%iT7Wv(_#3eQfldpJ`vNhrY_H?**7?k zl_u!HdRH~KN`lWHja0t6us3Q)w3skD`DL|E_gKyddm~jh!IWNCqvxB3djAS}xWdc< zj&2(n5!Ss?MVX1!?%Yfj@65&p)b55yDx=394$lgsa>y5meL>I}mzj{5hxx%2W1zKH1>KXd&0 z)1v*S#e;^N3nfj8+cEM(?^1ggbOR&r8qFfUbSXT-zW z?S`W4mj|LAq-l5j%L?Gnbn&)y;QXu$EyA7sXO0q{eiHw9{i}YGW;ua)6b3eDjZ^U= zYOqpEN~@$&q0_3?E9vURFIDv|&X=eha9_PxwKa1i@7?O-(p$+HT$WZq|EEiGG{-&9wX#R z{5Gx4Mza)9{85}P6!-Yh#DjZ}bRxmWOA<}Le@h$w{LCU#xAA0eb2s!H++k!Af;BNO zKfg#SWm=3vLHwxhWYufxWY5qmk|p8gE4RoMgdUN&LN-UVG8JJm&nhQ=3jJiw zUa0Yf)zI|q=!rGl$}UVh z?hs}k@wRbJL9FM8N_G(qn{5tjqs%t7S|ZA;uB5yVy_oY!TDM2Jp*va5psjaO{p(W;j1WdyUT#MhEuNja|b!Y{_m_@5YyTzWY* zjd#yZL3n*>_whpon(YG?`Fm}>F_;t=Y)5EV!+|3@3!}p`ch7Vq(x)_TYO8YIlSE;r z^qldvpJIEt-n{t%_jgk+BB@cxLoHFhfr?yqMZfthp>PJAqoJp>ru{>u#rch_@(JOe zuW&bCaoWite$PX&Gr)LqU4Bz*pYde%#QU-B+<@tX=gMxp$}_*257W0LcL(@xTp)YM zrC2iK#;~mVePX25@%HPhG9sZ5uh^o0r)9}GRoWx^vJF*EP|2H~bS%f;+V1D8w^R*ujl%Aaett7Ym%BH=Ux3i;p3b4q)Zha4Z)SD*~cnhB_@kY zb=?h1dS(w}*0|t({kr#6BZ-by68!qRXHC#&dlwG#JRYAx-g1A_m#ozQ2 zeYn~0S7QXNdJBP9fnRsBL${&zGCZS1R%%d?RY9DL=yJB&Yug*#SJAXo^w9T-|8_4x zbyu_x^UIr_W|zC8@WKmsiEQVW*+S9N&b;FWQYHL;pJqRKkM9vhm2e@#;J$oZq z1EmCmum(t3xDi4frD^eKd3zMs$a-1Cq=Z^o(OUGH#fO(-GoU;8&BdEhmnO2WTCwl! z)L>}h=}=25OFQ(RgaS-GZmD_GH6xaM)*;Yz%@0<(sHdRrQ5?y8bPn_)D@ zekcOwLw(>H14rt(`Y=vbQZ!LPi~Dn?Zun93?;chghb*LrOb@NiRgJze<|KVTsCVw% zN6)_U^;Tn3D^=JDimK5D7Zsret93K=_*g)|ABM4BVmNl26c(F(e}UeKKxX-+&sPnHm{z8&kun@MrrmiX)zoAYXdKT%L~jJvRt=r*u07w4Y}NTU^ecE z8Bm8-lHc(8dE*{eEl~m6@#$Z1ujX$c-s(gHD$>Mcd zmqWE;fE32llx&5>kNcO+F*dC_o${SaA~=c^+cIq*efKv`AVL}MWaE@8yE7z6?80jpMCMVCcB%0OzTU# zL7Jv5Ch_RZwR`0m;Q+P!cKTd=_WpFb*fWon?iAHJ>S(Q}8f2|Ufmzq@(TY)|9T9e! zC36(|-v2gX-Larsdb46h*Z5*ZOjE==gqQ%Y*Nr?w7SWt@gnQ;E!;MmksxW``{RuCH zn+yeKTP&+)3iug3WG&HohDvPeVydbz6D~V_qG&T3-zROXN+wmsUwZO^xG(*jxTXN_ z2K<3&vaC!CY3KLL$)5 z-J;NX>(=KRT_~K4Ynq!t*p%HdqmT%;sszmiX{Kg?7n^y7l3-2gu z9EU^LJ+%a>glV0`>>pIxhUUAMZWAf$#9e=aV}g2NzvFqAjPdH7iZ2HO-iC~L>vFF# zAuuyfpnkmMSi`daa3Vg#W`1%|A%o+) z3Xu(MiN~neu4Jp<852M~Wy%l($|seraBr8H+18lK%bq z{_{RD)I2xpC%3{AF&|Y462-Op$2vc&OeZQX0 zHI;~W8{AhsO_R8rM^nSDbUV>RRN;mzP-O||T8do`;|R6W7e+s~dbU%Q7p5jPdh|An zRy*qYD+cNPJJ!Cg^JM+Wqozj2ScR95Y#&LRDCT&6awPM5HSunU@Yu~9dxH@+Y;Y?{ z)I7~VEX%R}oO94CmAjgeC6c z#svp51Y=;k4p(fdL>Hf$7SVbm7%B)k7+&sg)PB_+OtK7}DXDi^V$t^U)RW?lNyc!` zy@>ksDzD4H9VTCL8kkOFfE%mO@=m$$ai`#qZ;o^pnSl5pVjb!s@34*Y~~Nzf@3>-a4;KhInIe|xrAWp6$hFZ80u89*I(ISSEOQb2a zBldB@8`HNdb*N;98oQQun+n;s7hcwqS(uD=4Z3yf2mgL>yyyMz5tv*{*p|+m!o4{( zc%JqC>3NhBNzVQ&RCaT(5q49nE1ux0W5>ZKq(wYAl?wG+bmfD1Wu901bn%}fFeULp zFEFB|5*eLmE%ccKS&!+UaLE;KSrW}R$0CyzzT3yz@Y~}%hq4B{y$1x(w6Z9Ub>c_0 zQDk^7hXx9L)Jxm%b;IXVun`^htlv-$3-uFvr-|;-FOdVlmO1yfWkyLLp2u?=(EL!AHn?;nzSTv%-gf6a1-$7@xagsI1D`8VW>3w@rUU81 zlc-F58R-NzfDi5HwVKjpRNdTog0#7qZy8(`6&bB@i6||1A^PoY?Qz_ps-~E*`UrP= zbYga<(1n`#7j~Ww$O=<8C1hcr;cZW<0+OT6+Qx%c{bU>oW!6ud7q(rMW;hsUpCw=e z?r_u`ILy;<5CM6?G)-nlmOq|YVDO+Qp1Qf3LF$m*Cqi0Q zQfPzwgl^bO4x{tBWcBd5-gk=c`;&n`0;5iZV=>mXUKh~98XpN$+YYQdKfEf)?X`K; z)^ia5@y6$feGcjI92EJ>!HMlv^E|_(oaaImR}qAyCOu8HwLfOle(d=`*DAC+RK^KG zSN=%9>T>C^e=f|?LIUshVJ?x*X`qS6dm8VHytS2di+Z1ncppX3X9EjGDJ}j48WXI< z@`pSd16Z-=O>)KCYwt0LL|yY5oU9wNhojromot(L-)%-_`SRVW#tGi3M>3gXb%c%k zulMQ3x{;bFds}s_FA3gP7|+WoAh$};^UCn-vIC^iEr%e_+NCS&F)}rovFD%#n^B4> zf!R00A0maD<5sY2dx?35y`z=y+xSNJKCzjS_wEum3kn~aiWW*K2Ve9OZRoh{;X-fF zIX2rXN5qxixsN-@f6X?@>LP#s`jc2Jw(^O`M+;tJ`+$>LUKR4zO|_wFK4=Ae=C04^ zSCEY(s29g&e1-6ssoPE)MV&o>w5fPtCR?qAr1SnvSm+BMihq1FG2~FeJOwMF^5zjy zeu==Lx_QZdsb=Q$Y>rav2Vc}%bphfqlHW|^40PAubN`wBcR5sCh$gi>GL|p3!t{F~ z)!(8PP6Nt)_!h>GjEe;kwryq}AAQq!#xqJhyIvtv#6#t}_6482SoyVu*jS+pFVMDRE z=7TA7(SN@-kkN>?JKI`Cd6m9BGRCYfiDyr(o3y=#(EPEqWSIz@P3`KfLH?dv(NJIC z)-8!9+aRS!qJ?QA6{yw&#Da!Ly5jjS9MBH1_gqH46Tzh^-H_J@Ei~pH6hxjpM|DN@ zTwQq~J6`@6^LPXzm*jX^jx&A*KT}ZVY&c6XLr>!8yvux9#?$n$b=V7(a_){1?-m||j`q^){i9wyd4z_274Nku0ppLGAtgX!EsThRAh&Ei;{ZZ&zSXQs+1*WX&Mtgev`YxD_{xqfM!tUPWKp@K$ z&O!xK`S2~uC*PmWbmKV)r?lz2_${QmMiKSetS1Xku*bc;P%t2ibRmOLOPYO&{& z?8c*eEK+gX#Bq`e|MgO`&19(I6!VEF^$9ND?L!e8!|JB|n#0Oa4x&Aae3A^mw9%H! zjL_EWW`~@ARvORTjptcqrj**&$+zpHTH2dKXnLOLP)WUf-F#$P~LO+42MNC~9D=wkDYQUU{9!S$578 zw70hbJTT(cL%QC<^vvAJ3O!RrQlp|`ZANM93+970q2o!C=^3iSh3D-kvCaurRy=yF z8KMn*H))1)&1z{(vDFxL0x1`9{fx>oaoK9T2$rcjr^1bm!!=*;koQd+f=*6O8@?2E zo?$O4d}%2*Y`@m;lF{`R6d^~=+(qY_>77I?>H?T2TUYe`7Ou9(5Dea-Y14Qe8ivcz zi?g{Zm9aXc|NW(|g~X`Yc#N)*-AgfU+#d#M`Gs(*Jd*04yEg)F=cnbf=k%4&d%qBU z5oP&!9=BBP8Fr*l4cV+?s5LFblk%eoO`I+wv;X6Uz80S$n=*A~RMNONmj9jzg?J-x z=)(K2oY0pIZXe#3uu0@TPScoXbl3a@|ult@>`h2p!wHnXk!>mWSpz&&^nd4%yIJCooR! zr znzGbQeZ7*b5_$6->Qhs%_TyZJ%M}Wncz8tShbTkLeeLi8r`?kOr3Wy^&gSJjn-MFln3si{-93Dh&54Op@=G4^2Ty*4?FoJXmXURR*4x%m(_ znr}4LY_Oc(iH}9SKW-^)l$d8`UcV=iF3;` zq-DPz;1VkDg9jB&1CHvjHtlYxWA5#bz@w0VQCVvCAM^cl>^gdU9A=#>6msfJs-#C1;&Ah%V zw1xDb;jTA|TI+&w52H=fbnCgZE9f^$iit@hAz`3}?Ba=MbP4Z!tTKxVB&|N{BGxF? zCF7}Ki)+=v@ea7CzOxbK*Zt3Mzal7AmFMNctxI!VhqRZ4Z4oG;lNfjijdk|4BA>Rvq@mvF+ z8$mjgvQh$X*)O9bVQhv!)k@O8gN9Jo`vSxALDWCaBd7P1km?%mN$(IBwH8jg%50~W zw_tMa6}JYfC{SjHU~9X0 za2CnFvkTzCHWsgD6i0?^$9P` zLTg!REu>S&MDSv#(;vy51G5-~T%tpu!LDg7TRzn7&m6<9E=Ea}fj3NRf^TRNz4VW# z0^d_)cY8urC(2i^PdpHKIZ#nybusKNY$=RQmNap;xwX5`MoqxPl4~#Hzq)TKJmiX; zubQ;$B1<>h4VT`zq&4%eI|0rP0MoqLU@5a@;$W2|5Vzq6Wk;<%N6DD%&#qOVqH4r? zm{^Hmk1|%G$G`G%txu36rM@L_B+iIspS>>sUPW6+;K_bR;Pem;O*Bc0(=?!7t%gXg z;WgOe4Wq&3N`$iD?M3Z+%`GTiiF)Yr_4S>Algio_wosOA*_T)nEVR(z^mM$DA&dgH zWA|TO4N>Dmn2@{;gAuTiKfv6>Bj3#$0P{+Ol~vmbLTk)Ff(BtzOu3zskn0mt1)?>W z*CTa6karz-KdiCR@pE;n<9siL7Q>*8Um25m7QHexcVh>D;#WsLDAc zUN;u)XDcGn8aD3hm_WY#rR;o;U;j!UHmf2EFl*!9c|jzZmjJgK_TSNpbUL}-m)5#} zrfdMZDufz!aEksW>3<|M_C7T;_5sOgRO1@_xDQjhLk+N?>%Myxd8xMMM?*jbc(^!h z1c3hf)Uu1fk$kLNLJ}Mv&5~C6gJ1xtcZ5!Le{}L-*g6woC)6wskC(!{r>%pH6b2PH zp<>2i_pk!gAJEB`(F4AiNOo9sg67YC>lS2EXBXa%r`~-42W$@r@BLdAFZ6}z`__Ii z)TId@sWf@yr36;4UZaar1HIP%k}hB)IGs~mqwSIMZAqxaJ`1S-5w z_=Ll>VbwecsE2Ev>F`~y)zT;QtwtbbscfQ>d{~T_tRQm9p5wPyOdqkENRCi}X_op8 zvmN~rDoL{t-cy0;X5)XQErER;Dp!DawY%Z->nX-YnI4d1|B+-i>dPOlB1HnC)2Nrd zQ_pleyHV8pXHT~_AG5|&T(cIj@%;gZr650g+gN;yxae^_;Ok%AZns-T<^*Lrr%mrD z&cKclm-3M*nxduaALT!gRs^<{+_Hnq@nJW8(SnAcN!!%MZmO8v)pKPE^7#?Pd&Vrf z247b9HP^a$#vJM^#P`r~E()`z28pTulo!MPwszLlG#IcNk!a=dhxQ9fxccyNu5<9O zsS%t!d6viHu+FE~TA-QvGy8@$pgG_lMKkW`myW5Vec{c1&jjiKmzZ4LMtnKihW#C% zPpgfAgGb`^>ubl&-3!*1YqVEJc~c7W#59?)lnx(IGOtYX@-A|M`NwOvZ3+bR3jalI zn+9M8w{yWh%KI>b0CVSc&Ku~~R3Jbn+C|ho$QB(5E#k8K&JW(cHkSTp+2p%bjyGcJ zB$1s)x=pHFDBs@JwEyj_^TIh!%bt)?*`jxYe9kzmt>NZ4C36*QmmF;!0AE{kH}m6R z^`2GF`e!=l-MJrpmbRVG+n7MxA2^r}dWlj8H-9=`gU~nZYUyp>)zC4<_c3u#d6|nZ z>7Gr1^-$FP^KLO*<7zckV@{zy4$r3gkjW;=69lv1i0k;d%w8--%L>zfd(&EUTWVsS zfu^AAEJ?RJ@RlR2APIzw)+ob-mX!#O*-r~hzEU#L+uhGK7w-~2oXV%93N%fqPY`Dt z30B?7h#hAA>;L(moVxhR`j7@9yP~RxdGgEsze^t~0vR_dpZt4A>OfZqF0^rLPwF}e zHqG+n4DL4e6K&Ktv6jHYH=RREB{ofjhSF=q%-teH8{v>?oAQzEz~A}52%LbFsTCN*TVN^M;VEg7x3Hh#iUQGVY2zj_jH^Y4&1)b$3e z_J9PSjf?dubHILA9Wc#73|?2zU6>R;Jn{>a-!8Y=4)#Guf`%x_y6 zEzJ7f1Vuu+eUvYjjUnk~ACJ;u52&a!;Z*wdy-5UeYANXSZNRv|M{&*~Al}-Accn3n zc7P##+*Njk;`qrOA#;d^X9F2`0^RS~FWeQ+I4ub7X62(N6ec^Og}&>*yxqH1`*AOp zeu?4m?cy1C#d))}ccVP7i@hJ6EA!r3ay2VAY|)|{2LC>67T4h%{xSNNon&#d+PFIX zhTas&z?lG(NG3fo6c^VQjS_La`;}lu5+_4RmQ4DXFMC<^D!9Xz!r9!GIV?!>u$)B0 z(e+tnA$>f43hy_hGUGp1I}DH%nVH%ge(H%B6!v%#ipr+p&&qAQibgeHEd7( z86U3Tqy9fHfbcBK^Ou&u50?hy?Y!xW^sb7e4DPxTQKDUA?mtomdzDBTl$p>AKusZq7P?kM@#-o{zEulawd@IY5e|^RWg!ws_jSNzrL)47vrdAboXC|>&s2!i+nG58+G$9I@!CZ;5h-> zS@swjv}B=2%;`&S#sPh%eIZU5FRNdLQ-oAL=GQRRi__g8_74_d>LsrbYy$&UZ^eXG zoQ)faYdz>rhxg$_ZpdBOq7f#q6E413LADBR;eux%xRlR^PA$dN{fBb^m1)sv1n)^|bcZqwN)aXik+O zGS;cwYcLfv^_>YZopUp|hTnue!>g8!TKXO_YXah-Q;7$F&}MvTV=42qgl4?_J6LF# zNt}k?-~hlUNbm(m1W4kwI8a^_|3FG0xVx452Xt;j6ne0~ z*$?qx^cqm9T$;E?b$MJ!QeGZB^PDZjimkU zM$-(wJ@gTKI>blPY%a=^aHVnEx$bbaD`=n&m@zKa6iC(^VV2-$U@h`UXDG>&ulf^p z-=CP)yCCYw$FR>A<{P`Ag7d!niQ47jG&*jOWV{LxgZ@Gq%3^ai`git_OmpQzQE8B< zBVSnFWwm8}&G?bXWGY|^M&J))&4|wM%>Tn}m?6+@$C3KEhXipbOaKCMho*Os_y*U?46noLz*~WJWo1yM}?6McNm5~ zZ+toeb2|_jLXIyKyMpgV%%a-cslI^%dMF!}f%g=`A#q2C_HZ+ZL2RJ+9xLPX=jHG8 zvS2N4Fq`6C?|L)3eF z93PE|THT^QZdf=;=z8775%lv6Yqjps7Xp)wx)7{RKcKru&|FbM0wgwAH}MX4=yVDH zy{Qj6s~ZY~X>D598!J1Qn$w;$ksHz6wRFBAfk29DkqkfR>P#4o*<_$S3`vSlYRUIU z;{cRz$RQI`MI-C=wEah16p?3?;b+u_X5fE*vS!0dCJ>P5?M&+#^y<>>@Gsa!r$Clv zOwb+u!`Kl0WLnH6E)qurh^7tBED@n@we~(7(z;|oCo9gYjN7SW!vbcgZ2A<9okhCp zeyDe}vpP(?BI;mHhG@uua!K?e4`Ugha;U-3=D>n+v6g;)j9s+eyuOH~%8mOqJ9i@0arckZi(h4PGh@ z)-+`zCH?5UM4Y1b`oeq?%^*3v4jOo#7sFQYfqqcNA=3<`HI(;a!53f<%bhnR53*!d#+uxX zSVXixNxwln1Dj`20k_xwg_Yv>NPf?FVS&M?%r5zg{VO-$E{Wd9*rh4P9dQBB1+9T* z_KZrO4zxN@JAHuDpY|o)Fsr#q&#Awr-^bPx=6J54bv+@Nf>Ce?;2%yNIUwXD1Fo|;Pba{T@52i;@-KuDrE2EZ7MUd=@hLA zLQ0sW?B()C>RanM(tU}Z(JU}%RJA@;Rq4jD#{-4z6N_=W-^@8HdEOP> zNF6A1#^UtZzNSZkXCSlgFb3Qn{EqJ_X&T}~4jzMeFs#+ZDZ)a$Ex!Z~Ax3hIU^GyY zmiEa)1y%o%Wl<8rA}=h3MKM8} z$e__tS8OWAKNoi)5qmg|v`atgW*Ge44N;2d&he}<;kk#{vlBWg||R`U`nA+`G2Jp;0Kv)=`1sgvp%R#qf69$H~y({;FVlz zhrnIf-M?_iR5GYZ`t2oiUgA++xe~n)x|#X-k{MVqQQ-YEe`EFWLgFz>6f(MWhx!2$ zHlxp0Ua@qNRzAOitO1&^>c+VGMI+j_Pa7=KIq{fZ6n(6L93-Yru+w3_(MRnkR4yk~ zyCm#ksR7sO(nHng=@k5iBLJe#s9?ZmYh5jz-XvsyTA9v^P`0!}Hhg{ zwZ=$F&6|1LiY7VbSvs1>xd4_}$v9H$eJt zTft=Zy|-6ZeU(1a(L<)mcW~<{qIW-f`Vg8OI=={Hq^f?OAhkx`ZEtB|?-5x`?AxS# z&lS>JxBQoG& z`{>WpYyW^4kGPP$&mLT)*?28Hx&_#9=LAp+O{E_|s-_K}8;_K!|EDoU0&h7FZLkuH zXTJfH$FzYOl+Mom;TCkH{k4IZ*(!-tL@HX$PWtyelLMT;&I zDS*TO`n;Pf1yfCOg5LvK136PXFM>oR@gu zx5L8dd^=T!JJ>}aqJ zQ41v6CHp!)H^W7I50P#TuWuwkK^gmzUHyqio|kiwi|?&(VhK(B_lMs-7YtDW+;A~K ze$12!&4-Q4S<}Ufnp5ytp>nB*Q*KRRPSWVBEDH2EM{>!4GE9LT zwV(p>Q75KqSWWie?LrgtagLl|Usz|3(PT!QoLc6V&lKSAm@MnRg)A)~+ZdV+Czqn4aeJyb>|Ry3lyov4LB}++3eALORiZXuQKQ)F3)v zAS*AABNKBRe#elmhCQ@X13>qK_z4wH!bgD23%ob_%8U3Q#<3jKKYe)liSU~ibdKRy zJtTK58-JppD$x0Fn6`w^*QqKr8a&b*7;-}k^RC#*iEH?h=l^>-f~~HOoi^dy{FHoF zepFm0N%wBU+t2PW`T0NO#`jpoZpZ?LQbM3dsr{#4L`f?#{ zO`LXTfMFUV#r(%Ai@`s7C{=-PPdYt!k<-U5zXFyoReniakhGLE5_#ECuogI|kYq_u z%oD}pip=97oO%$bAm@pAQH{+1)EMDX=7kDAs@!PopQgJV_r#cO2kZ9|jkIMm>vlh$ z1Emw?cMz4F66p2i$i!5 z^k!D#8%&J86g@y@CV*M!;iQMND;EK+MLcGZEhK0%TE3(h=wO9#$E%tYaPJ)}bqbvC zY7h8n;;}|tMtJwD;Wq9OL}CDOuETJRR$Wft&03{$#T#t%8p*7>udosEs*KEIV=YAo zV&@|^zEZ6SQ2gkiQX^VPO
  • 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%0D`=rKn?$bC6tF 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 diff --git a/HandsetDetectionAPI/bin/Debug/Ionic.Zip.xml b/HandsetDetectionAPI/bin/Debug/Ionic.Zip.xml deleted file mode 100644 index 24000e7a..00000000 --- a/HandsetDetectionAPI/bin/Debug/Ionic.Zip.xml +++ /dev/null @@ -1,18168 +0,0 @@ - - - - Ionic.Zip - - - -

    - 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. - - - - - 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. - - - - 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. - - - - 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 - - - - 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. - - - - - - - - - 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. - - - - - 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. - - - - 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. - - - - - 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 - - - - 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); - } - } - } - } - } - - - - - - - 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). - - - - - 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. - - - - - - 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 - - - - 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. - - - - - - 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 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.) - - - - - An enum that provides the various encryption algorithms supported by this - library. - - - - - - PkzipWeak implies the use of Zip 2.0 encryption, which is known to be - weak and subvertible. - - - - A note on interoperability: Values of PkzipWeak and None are - specified in PKWARE's zip - specification, and are considered to be "standard". Zip archives - produced using these options will be interoperable with many other zip tools - and libraries, including Windows Explorer. - - - - Values of WinZipAes128 and WinZipAes256 are not part of the Zip - specification, but rather imply the use of a vendor-specific extension from - WinZip. If you want to produce interoperable Zip archives, do not use these - values. For example, if you produce a zip archive using WinZipAes256, you - will be able to open it in Windows Explorer on Windows XP and Vista, but you - will not be able to extract entries; trying this will lead to an "unspecified - error". For this reason, some people have said that a zip archive that uses - WinZip's AES encryption is not actually a zip archive at all. A zip archive - produced this way will be readable with the WinZip tool (Version 11 and - beyond). - - - - There are other third-party tools and libraries, both commercial and - otherwise, that support WinZip's AES encryption. These will be able to read - AES-encrypted zip archives produced by DotNetZip, and conversely applications - that use DotNetZip to read zip archives will be able to read AES-encrypted - archives produced by those tools or libraries. Consult the documentation for - those other tools and libraries to find out if WinZip's AES encryption is - supported. - - - - In case you care: According to the WinZip specification, the - actual AES key used is derived from the via an - algorithm that complies with RFC 2898, using an iteration - count of 1000. The algorithm is sometimes referred to as PBKDF2, which stands - for "Password Based Key Derivation Function #2". - - - - A word about password strength and length: The AES encryption technology is - very good, but any system is only as secure as the weakest link. If you want - to secure your data, be sure to use a password that is hard to guess. To make - it harder to guess (increase its "entropy"), you should make it longer. If - you use normal characters from an ASCII keyboard, a password of length 20 will - be strong enough that it will be impossible to guess. For more information on - that, I'd encourage you to read this - article. - - - - The WinZip AES algorithms are not supported with the version of DotNetZip that - runs on the .NET Compact Framework. This is because .NET CF lacks the - HMACSHA1 class that is required for producing the archive. - - - - - - 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. - - - - - 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.) - - - - - 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). - - - - - 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. - - - - 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. - - - - - 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. - - - - - 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. - - - - Close the stream. - - - - - Flush the content in the stream. - - - - - This method throws a NotImplementedException. - - - - - This method throws a NotImplementedException. - - - - - Returns the final HMAC-SHA1-80 for the data that was encrypted. - - - - - Returns true if the stream can be read. - - - - - Always returns false. - - - - - Returns true if the CryptoMode is Encrypt. - - - - - Getting this property throws a NotImplementedException. - - - - - Getting or Setting this property throws a NotImplementedException. - - - - - Issued when an ZipEntry.ExtractWithPassword() method is invoked - with an incorrect password. - - - - - 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. - - - - 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. - - - - 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 - - - - 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. - - - - The System.IO.Path.GetRandomFileName() method is not available on - the Compact Framework, so this library provides its own substitute - on NETCF. - - - This method produces a filename of the form - DotNetZip-xxxxxxxx.tmp, where xxxxxxxx is replaced by randomly - chosen characters, and creates that file. - - - - - - Workitem 7889: handle ERROR_LOCK_VIOLATION during read - - - This could be gracefully handled with an extension attribute, but - This assembly is built for .NET 2.0, so I cannot use them. - - - - - 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 - - - - 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. - - - - Flushes the underlying 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. - - - - Gets the wrapped stream. - - - - - The count of bytes written out to the stream. - - - - - the count of bytes that have been read from the stream. - - - - - 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. - - - - - 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. - - - - - 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. - - - - - - 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. - - - - - - - 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 - - - - - 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. - - - - 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. - - - - - 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. - - - - - 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. - - - - - 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. - - - - - - - - - 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. - - - - - - True if the referenced entry is a directory. - - - - - Provides a human-readable string with information about the ZipEntry. - - - - - 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. - - - - - - - - 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 . - - - - - - - - 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. - - - - This property is only partially supported in the Silverlight version - of the library: applications can read attributes on entries within - ZipFiles. But extracting entries within Silverlight will not set the - attributes on the extracted files. - - - - - - - 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 - - - - - - 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. - - - - - 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, or on Silverlight, using UTF-8. - - - - The content of the file, should it be extracted from the zip. - - - - The name, including any path, to use for the entry within the archive. - - - The ZipEntry added. - - - - This example shows how to add an entry to the zipfile, using a string as - content for that entry. - - - string Content = "This string will be the content of the Readme.txt file in the zip archive."; - using (ZipFile zip1 = new ZipFile()) - { - zip1.AddFile("MyDocuments\\Resume.doc", "files"); - zip1.AddEntry("Readme.txt", Content); - zip1.Comment = "This zip file was created at " + System.DateTime.Now.ToString("G"); - zip1.Save("Content.zip"); - } - - - - Public Sub Run() - Dim Content As String = "This string will be the content of the Readme.txt file in the zip archive." - Using zip1 As ZipFile = New ZipFile - zip1.AddEntry("Readme.txt", Content) - zip1.AddFile("MyDocuments\Resume.doc", "files") - zip1.Comment = ("This zip file was created at " & DateTime.Now.ToString("G")) - zip1.Save("Content.zip") - End Using - End Sub - - - - - - 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, or on Silverlight, using - UTF-8. This encoding is distinct from the encoding used for the - filename itself. See . - - - - - - The name, including any path, to use within the archive for the entry. - - - - The content of the file, should it be extracted from the zip. - - - The ZipEntry added. - - - - - 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 or Compact Framework - versions of DotNetZip. - - - - Developers using COM can use the ComHelper.CheckZip(String) - method. - - - - - The filename to of the zip file to check. - - true if the named zip file checks OK. Otherwise, false. - - - - - - - Checks a zip file to see if its directory is consistent, - and optionally fixes the directory if necessary. - - - - - - In cases of data error, the directory within a zip file can get out of - synch with the entries in the zip file. This method checks the given - zip file, and returns true if this has occurred. It also optionally - fixes the zipfile, saving the fixed copy in Name_Fixed.zip. - - - - This method may take a long time to run for large zip files. It - will take even longer if the file actually needs to be fixed, and if - fixIfNecessary is true. - - - - This method is not supported in the Reduced or Compact - Framework versions of DotNetZip. - - - - - The filename to of the zip file to check. - - If true, the method will fix the zip file if - necessary. - - - a TextWriter in which messages generated while checking will be written. - - - true if the named zip is OK; false if the file needs to be fixed. - - - - - - - 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. - - - - 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. - - - - Provides a string representation of the instance. - a string representation of the instance. - - - - 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. - - - - 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. - - - - - 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 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 FileSteeam(filename, FileMode.Open)) - { - using (var zip = Ionic.Zip.ZipFile.Read(inputStream)) - { - zip.AddEntry("Name1.txt", "this is the content"); - zip.Save(inputStream); // NO NO NO!! - } - } - - - - Better like this: - - - - using (var zip = Ionic.Zip.ZipFile.Read(filename)) - { - zip.AddEntry("Name1.txt", "this is the content"); - zip.Save(); // YES! - } - - - - - - The System.IO.Stream to write to. It must be - writable. If you created the ZipFile instanct by calling - ZipFile.Read(), this stream must not be the same stream - you passed to ZipFile.Read(). - - - - - 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. - - - - - - Saves the ZipFile instance to a self-extracting zip archive. - - - - - - The generated exe image will execute on any machine that has the .NET - Framework 2.0 installed on it. The generated exe image is also a - valid ZIP file, readable with DotNetZip or another Zip library or tool - such as WinZip. - - - - There are two "flavors" of self-extracting archive. The - WinFormsApplication version will pop up a GUI and allow the - user to select a target directory into which to extract. There's also - a checkbox allowing the user to specify to overwrite existing files, - and another checkbox to allow the user to request that Explorer be - opened to see the extracted files after extraction. The other flavor - is ConsoleApplication. A self-extractor generated with that - flavor setting will run from the command line. It accepts command-line - options to set the overwrite behavior, and to specify the target - extraction directory. - - - - There are a few temporary files created during the saving to a - self-extracting zip. These files are created in the directory pointed - to by , which defaults to . These temporary files are - removed upon successful completion of this method. - - - - When a user runs the WinForms SFX, the user's personal directory (Environment.SpecialFolder.Personal) - will be used as the default extract location. If you want to set the - default extract location, you should use the other overload of - SaveSelfExtractor()/ The user who runs the SFX will have the - opportunity to change the extract directory before extracting. When - the user runs the Command-Line SFX, the user must explicitly specify - the directory to which to extract. The .NET Framework 2.0 is required - on the computer when the self-extracting archive is run. - - - - NB: This method is not available in the version of DotNetZip build for - the .NET Compact Framework, nor in the "Reduced" DotNetZip library. - - - - - - - string DirectoryPath = "c:\\Documents\\Project7"; - using (ZipFile zip = new ZipFile()) - { - zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)); - zip.Comment = "This will be embedded into a self-extracting console-based exe"; - zip.SaveSelfExtractor("archive.exe", SelfExtractorFlavor.ConsoleApplication); - } - - - Dim DirectoryPath As String = "c:\Documents\Project7" - Using zip As New ZipFile() - zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)) - zip.Comment = "This will be embedded into a self-extracting console-based exe" - zip.SaveSelfExtractor("archive.exe", SelfExtractorFlavor.ConsoleApplication) - End Using - - - - - a pathname, possibly fully qualified, to be created. Typically it - will end in an .exe extension. - - Indicates whether a Winforms or Console self-extractor is - desired. - - - - 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. - - - - 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. - - - - - 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. - - - - - 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 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. - - - - - The default text encoding used in zip archives. It is numeric 437, also - known as IBM437. - - - - - - 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. - - - - 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(). - - - - - - - - - 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. - - - - - - 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. - - - - - 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 - - - - - - - - - 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. - - - - - - - - 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. - - - - - - 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. - - - - - 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(). - - - - - 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. - - - - - 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 - - - - 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. - - - - - 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. - - - - - 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 - - - - Flush the stream. - - - - - 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. - - - - 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. - - - - - 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. - - - - - Compressor State - - - - 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. - - - - - 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. - - - - 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 - - - - The blocksize parameter specified at construction time. - - - - - 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. - - - - - 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. - - - - - Close the stream. - - - - This may or may not close the underlying stream. Check the - constructors that accept a bool value. - - - - - - Flush the stream. - - - - - 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. - - - - 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 - - - - 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. - - - - - - The blocksize parameter specified at construction time. - - - - - 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(). - - - - - Returns the "random" number at a specific index. - - the index - the random number - - - - 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. - - - - 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. - - - - - Flush 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 - - - - 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. - - - - 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. - - - - - 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. - - - - - 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 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(). - - - - - 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. - - - - 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. - - - - - Flush 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 - - - - 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 CRC on the GZIP stream. - - - This is used for internal error checking. You probably don't need to look at this property. - - - - - 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. - - - - 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. - - - - - 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. - - - - - 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. - - - - - 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); - } - } - } - } - - - - - - 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. - - - - - 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(). - - - - - 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. - - - - - - 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. - - - - - 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. - - - - The Adler32 checksum on the data transferred through the codec so far. You probably don't need to look at this. - - - - - 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. Defaults to 8192 bytes. - - - - - The minimum size of the working buffer used in the ZlibCodec class. Currently it is 128 bytes. - - - - - 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. - - - - - 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. - - - - - Flush 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 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. - - - - 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. - - - - - 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. - - - - - 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. - - - - - 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. - - - - - - Indicates the total number of bytes applied to the CRC. - - - - - Indicates the current CRC for all blocks slurped in. - - - - - 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 - - - - 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 - - - - Flush the stream. - - - - - 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. - - - - - 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 . - - - - - - Indicates whether the stream supports reading. - - - - - Indicates whether the stream supports seeking. - - - - Always returns false. - - - - - - Indicates whether the stream supports writing. - - - - - 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 - . - - - - diff --git a/HandsetDetectionAPI/bin/Debug/nunit.framework.dll b/HandsetDetectionAPI/bin/Debug/nunit.framework.dll deleted file mode 100644 index ed6550bb0556d716de525cd64e1a6cefb8a945bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 151552 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 - - - nunit.framework - - - - - The different targets a test action attribute can be applied to - - - - - Default target, which is determined by where the action attribute is attached - - - - - Target a individual test case - - - - - Target a suite of test cases - - - - - Delegate used by tests that execute code and - capture any thrown exception. - - - - - The Assert class contains a collection of static methods that - implement the most common assertions used in NUnit. - - - - - We don't actually want any instances of this object, but some people - like to inherit from it to add other static methods. Hence, the - protected constructor disallows any instances of this object. - - - - - The Equals method throws an AssertionException. This is done - to make sure there is no mistake by calling this function. - - - - - - - override the default ReferenceEquals to throw an AssertionException. This - implementation makes sure there is no mistake in calling this function - as part of Assert. - - - - - - - Throws a with the message and arguments - that are passed in. This allows a test to be cut short, with a result - of success returned to NUnit. - - The message to initialize the with. - Arguments to be used in formatting the message - - - - Throws a with the message and arguments - that are passed in. This allows a test to be cut short, with a result - of success returned to NUnit. - - The message to initialize the with. - - - - Throws a with the message and arguments - that are passed in. This allows a test to be cut short, with a result - of success returned to NUnit. - - - - - Throws an with the message and arguments - that are passed in. This is used by the other Assert functions. - - The message to initialize the with. - Arguments to be used in formatting the message - - - - Throws an with the message that is - passed in. This is used by the other Assert functions. - - The message to initialize the with. - - - - Throws an . - This is used by the other Assert functions. - - - - - Throws an with the message and arguments - that are passed in. This causes the test to be reported as ignored. - - The message to initialize the with. - Arguments to be used in formatting the message - - - - Throws an with the message that is - passed in. This causes the test to be reported as ignored. - - The message to initialize the with. - - - - Throws an . - This causes the test to be reported as ignored. - - - - - Throws an with the message and arguments - that are passed in. This causes the test to be reported as inconclusive. - - The message to initialize the with. - Arguments to be used in formatting the message - - - - Throws an with the message that is - passed in. This causes the test to be reported as inconclusive. - - The message to initialize the with. - - - - Throws an . - This causes the test to be reported as Inconclusive. - - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - The actual value to test - A Constraint to be applied - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - The actual value to test - A Constraint to be applied - The message that will be displayed on failure - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - The actual value to test - A Constraint expression to be applied - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display if the condition is false - Arguments to be used in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display if the condition is false - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - An ActualValueDelegate returning the value to be tested - A Constraint expression to be applied - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - An ActualValueDelegate returning the value to be tested - A Constraint expression to be applied - The message that will be displayed on failure - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - An ActualValueDelegate returning the value to be tested - A Constraint expression to be applied - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Apply a constraint to a referenced value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - The actual value to test - A Constraint to be applied - - - - Apply a constraint to a referenced value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - The actual value to test - A Constraint to be applied - The message that will be displayed on failure - - - - Apply a constraint to a referenced value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - The actual value to test - A Constraint to be applied - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that the code represented by a delegate throws an exception - that satisfies the constraint provided. - - A TestDelegate to be executed - A ThrowsConstraint used in the test - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - Used as a synonym for That in rare cases where a private setter - causes a Visual Basic compilation error. - - The actual value to test - A Constraint to be applied - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - Used as a synonym for That in rare cases where a private setter - causes a Visual Basic compilation error. - - The actual value to test - A Constraint to be applied - The message that will be displayed on failure - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - Used as a synonym for That in rare cases where a private setter - causes a Visual Basic compilation error. - - - This method is provided for use by VB developers needing to test - the value of properties with private setters. - - The actual value to test - A Constraint expression to be applied - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that a delegate throws a particular exception when called. - - A constraint to be satisfied by the exception - A TestDelegate - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that a delegate throws a particular exception when called. - - A constraint to be satisfied by the exception - A TestDelegate - The message that will be displayed on failure - - - - Verifies that a delegate throws a particular exception when called. - - A constraint to be satisfied by the exception - A TestDelegate - - - - Verifies that a delegate throws a particular exception when called. - - The exception Type expected - A TestDelegate - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that a delegate throws a particular exception when called. - - The exception Type expected - A TestDelegate - The message that will be displayed on failure - - - - Verifies that a delegate throws a particular exception when called. - - The exception Type expected - A TestDelegate - - - - Verifies that a delegate throws a particular exception when called. - - Type of the expected exception - A TestDelegate - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that a delegate throws a particular exception when called. - - Type of the expected exception - A TestDelegate - The message that will be displayed on failure - - - - Verifies that a delegate throws a particular exception when called. - - Type of the expected exception - A TestDelegate - - - - Verifies that a delegate throws an exception when called - and returns it. - - A TestDelegate - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that a delegate throws an exception when called - and returns it. - - A TestDelegate - The message that will be displayed on failure - - - - Verifies that a delegate throws an exception when called - and returns it. - - A TestDelegate - - - - Verifies that a delegate throws an exception of a certain Type - or one derived from it when called and returns it. - - The expected Exception Type - A TestDelegate - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that a delegate throws an exception of a certain Type - or one derived from it when called and returns it. - - The expected Exception Type - A TestDelegate - The message that will be displayed on failure - - - - Verifies that a delegate throws an exception of a certain Type - or one derived from it when called and returns it. - - The expected Exception Type - A TestDelegate - - - - Verifies that a delegate throws an exception of a certain Type - or one derived from it when called and returns it. - - The expected Exception Type - A TestDelegate - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that a delegate throws an exception of a certain Type - or one derived from it when called and returns it. - - The expected Exception Type - A TestDelegate - The message that will be displayed on failure - - - - Verifies that a delegate throws an exception of a certain Type - or one derived from it when called and returns it. - - The expected Exception Type - A TestDelegate - - - - Verifies that a delegate does not throw an exception - - A TestDelegate - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that a delegate does not throw an exception. - - A TestDelegate - The message that will be displayed on failure - - - - Verifies that a delegate does not throw an exception. - - A TestDelegate - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display in case of failure - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display in case of failure - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - - - - Asserts that a condition is false. If the condition is true the method throws - an . - - The evaluated condition - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that a condition is false. If the condition is true the method throws - an . - - The evaluated condition - The message to display in case of failure - - - - Asserts that a condition is false. If the condition is true the method throws - an . - - The evaluated condition - - - - Asserts that a condition is false. If the condition is true the method throws - an . - - The evaluated condition - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that a condition is false. If the condition is true the method throws - an . - - The evaluated condition - The message to display in case of failure - - - - Asserts that a condition is false. If the condition is true the method throws - an . - - The evaluated condition - - - - Verifies that the object that is passed in is not equal to null - If the object is null then an - is thrown. - - The object that is to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the object that is passed in is not equal to null - If the object is null then an - is thrown. - - The object that is to be tested - The message to display in case of failure - - - - Verifies that the object that is passed in is not equal to null - If the object is null then an - is thrown. - - The object that is to be tested - - - - Verifies that the object that is passed in is not equal to null - If the object is null then an - is thrown. - - The object that is to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the object that is passed in is not equal to null - If the object is null then an - is thrown. - - The object that is to be tested - The message to display in case of failure - - - - Verifies that the object that is passed in is not equal to null - If the object is null then an - is thrown. - - The object that is to be tested - - - - Verifies that the object that is passed in is equal to null - If the object is not null then an - is thrown. - - The object that is to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the object that is passed in is equal to null - If the object is not null then an - is thrown. - - The object that is to be tested - The message to display in case of failure - - - - Verifies that the object that is passed in is equal to null - If the object is not null then an - is thrown. - - The object that is to be tested - - - - Verifies that the object that is passed in is equal to null - If the object is not null then an - is thrown. - - The object that is to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the object that is passed in is equal to null - If the object is not null then an - is thrown. - - The object that is to be tested - The message to display in case of failure - - - - Verifies that the object that is passed in is equal to null - If the object is not null then an - is thrown. - - The object that is to be tested - - - - Verifies that two ints are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two ints are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two ints are equal. If they are not, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two longs are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two longs are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two longs are equal. If they are not, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two unsigned ints are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two unsigned ints are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two unsigned ints are equal. If they are not, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two unsigned longs are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two unsigned longs are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two unsigned longs are equal. If they are not, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two decimals are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two decimals are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two decimals are equal. If they are not, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two doubles are equal considering a delta. If the - expected value is infinity then the delta value is ignored. If - they are not equal then an is - thrown. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two doubles are equal considering a delta. If the - expected value is infinity then the delta value is ignored. If - they are not equal then an is - thrown. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - The message to display in case of failure - - - - Verifies that two doubles are equal considering a delta. If the - expected value is infinity then the delta value is ignored. If - they are not equal then an is - thrown. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - - - - Verifies that two doubles are equal considering a delta. If the - expected value is infinity then the delta value is ignored. If - they are not equal then an is - thrown. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two doubles are equal considering a delta. If the - expected value is infinity then the delta value is ignored. If - they are not equal then an is - thrown. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - The message to display in case of failure - - - - Verifies that two doubles are equal considering a delta. If the - expected value is infinity then the delta value is ignored. If - they are not equal then an is - thrown. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - - - - Verifies that two objects are equal. Two objects are considered - equal if both are null, or if both have the same value. NUnit - has special semantics for some object types. - If they are not equal an is thrown. - - The value that is expected - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two objects are equal. Two objects are considered - equal if both are null, or if both have the same value. NUnit - has special semantics for some object types. - If they are not equal an is thrown. - - The value that is expected - The actual value - The message to display in case of failure - - - - Verifies that two objects are equal. Two objects are considered - equal if both are null, or if both have the same value. NUnit - has special semantics for some object types. - If they are not equal an is thrown. - - The value that is expected - The actual value - - - - Verifies that two ints are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two ints are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two ints are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two longs are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two longs are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two longs are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two unsigned ints are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two unsigned ints are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two unsigned ints are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two unsigned longs are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two unsigned longs are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two unsigned longs are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two decimals are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two decimals are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two decimals are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two floats are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two floats are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two floats are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two doubles are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two doubles are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two doubles are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two objects are not equal. Two objects are considered - equal if both are null, or if both have the same value. NUnit - has special semantics for some object types. - If they are equal an is thrown. - - The value that is expected - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two objects are not equal. Two objects are considered - equal if both are null, or if both have the same value. NUnit - has special semantics for some object types. - If they are equal an is thrown. - - The value that is expected - The actual value - The message to display in case of failure - - - - Verifies that two objects are not equal. Two objects are considered - equal if both are null, or if both have the same value. NUnit - has special semantics for some object types. - If they are equal an is thrown. - - The value that is expected - The actual value - - - - Asserts that two objects refer to the same object. If they - are not the same an is thrown. - - The expected object - The actual object - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that two objects refer to the same object. If they - are not the same an is thrown. - - The expected object - The actual object - The message to display in case of failure - - - - Asserts that two objects refer to the same object. If they - are not the same an is thrown. - - The expected object - The actual object - - - - Asserts that two objects do not refer to the same object. If they - are the same an is thrown. - - The expected object - The actual object - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that two objects do not refer to the same object. If they - are the same an is thrown. - - The expected object - The actual object - The message to display in case of failure - - - - Asserts that two objects do not refer to the same object. If they - are the same an is thrown. - - The expected object - The actual object - - - - Verifies that the double that is passed in is an NaN value. - If the object is not NaN then an - is thrown. - - The value that is to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the double that is passed in is an NaN value. - If the object is not NaN then an - is thrown. - - The value that is to be tested - The message to display in case of failure - - - - Verifies that the double that is passed in is an NaN value. - If the object is not NaN then an - is thrown. - - The value that is to be tested - - - - Verifies that the double that is passed in is an NaN value. - If the object is not NaN then an - is thrown. - - The value that is to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the double that is passed in is an NaN value. - If the object is not NaN then an - is thrown. - - The value that is to be tested - The message to display in case of failure - - - - Verifies that the double that is passed in is an NaN value. - If the object is not NaN then an - is thrown. - - The value that is to be tested - - - - Assert that a string is empty - that is equal to string.Empty - - The string to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Assert that a string is empty - that is equal to string.Empty - - The string to be tested - The message to display in case of failure - - - - Assert that a string is empty - that is equal to string.Empty - - The string to be tested - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing ICollection - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing ICollection - The message to display in case of failure - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing ICollection - - - - Assert that a string is not empty - that is not equal to string.Empty - - The string to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Assert that a string is not empty - that is not equal to string.Empty - - The string to be tested - The message to display in case of failure - - - - Assert that a string is not empty - that is not equal to string.Empty - - The string to be tested - - - - Assert that an array, list or other collection is not empty - - An array, list or other collection implementing ICollection - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Assert that an array, list or other collection is not empty - - An array, list or other collection implementing ICollection - The message to display in case of failure - - - - Assert that an array, list or other collection is not empty - - An array, list or other collection implementing ICollection - - - - Assert that a string is either null or equal to string.Empty - - The string to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Assert that a string is either null or equal to string.Empty - - The string to be tested - The message to display in case of failure - - - - Assert that a string is either null or equal to string.Empty - - The string to be tested - - - - Assert that a string is not null or empty - - The string to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Assert that a string is not null or empty - - The string to be tested - The message to display in case of failure - - - - Assert that a string is not null or empty - - The string to be tested - - - - Asserts that an object may be assigned a value of a given Type. - - The expected Type. - The object under examination - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object may be assigned a value of a given Type. - - The expected Type. - The object under examination - The message to display in case of failure - - - - Asserts that an object may be assigned a value of a given Type. - - The expected Type. - The object under examination - - - - Asserts that an object may be assigned a value of a given Type. - - The expected Type. - The object under examination - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object may be assigned a value of a given Type. - - The expected Type. - The object under examination - The message to display in case of failure - - - - Asserts that an object may be assigned a value of a given Type. - - The expected Type. - The object under examination - - - - Asserts that an object may not be assigned a value of a given Type. - - The expected Type. - The object under examination - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object may not be assigned a value of a given Type. - - The expected Type. - The object under examination - The message to display in case of failure - - - - Asserts that an object may not be assigned a value of a given Type. - - The expected Type. - The object under examination - - - - Asserts that an object may not be assigned a value of a given Type. - - The expected Type. - The object under examination - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object may not be assigned a value of a given Type. - - The expected Type. - The object under examination - The message to display in case of failure - - - - Asserts that an object may not be assigned a value of a given Type. - - The expected Type. - The object under examination - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Asserts that an object is contained in a list. - - The expected object - The list to be examined - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object is contained in a list. - - The expected object - The list to be examined - The message to display in case of failure - - - - Asserts that an object is contained in a list. - - The expected object - The list to be examined - - - - Helper for Assert.AreEqual(double expected, double actual, ...) - allowing code generation to work consistently. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Gets the number of assertions executed so far and - resets the counter to zero. - - - - - AssertionHelper is an optional base class for user tests, - allowing the use of shorter names for constraints and - asserts and avoiding conflict with the definition of - , from which it inherits much of its - behavior, in certain mock object frameworks. - - - - - Helper class with properties and methods that supply - a number of constraints used in Asserts. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding only if a specified number of them succeed. - - - - - Returns a new PropertyConstraintExpression, which will either - test for the existence of the named property on the object - being tested or apply any following constraint to that property. - - - - - Returns a new AttributeConstraint checking for the - presence of a particular attribute on an object. - - - - - Returns a new AttributeConstraint checking for the - presence of a particular attribute on an object. - - - - - Returns a constraint that tests two items for equality - - - - - Returns a constraint that tests that two references are the same object - - - - - Returns a constraint that tests whether the - actual value is greater than the suppled argument - - - - - Returns a constraint that tests whether the - actual value is greater than or equal to the suppled argument - - - - - Returns a constraint that tests whether the - actual value is greater than or equal to the suppled argument - - - - - Returns a constraint that tests whether the - actual value is less than the suppled argument - - - - - Returns a constraint that tests whether the - actual value is less than or equal to the suppled argument - - - - - Returns a constraint that tests whether the - actual value is less than or equal to the suppled argument - - - - - Returns a constraint that tests whether the actual - value is of the exact type supplied as an argument. - - - - - Returns a constraint that tests whether the actual - value is of the exact type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is a collection containing the same elements as the - collection supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is a subset of the collection supplied as an argument. - - - - - Returns a new CollectionContainsConstraint checking for the - presence of a particular object in the collection. - - - - - Returns a new CollectionContainsConstraint checking for the - presence of a particular object in the collection. - - - - - Returns a new ContainsConstraint. This constraint - will, in turn, make use of the appropriate second-level - constraint, depending on the type of the actual argument. - This overload is only used if the item sought is a string, - since any other type implies that we are looking for a - collection member. - - - - - Returns a constraint that succeeds if the actual - value contains the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value contains the substring supplied as an argument. - - - - - Returns a constraint that fails if the actual - value contains the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value starts with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value starts with the substring supplied as an argument. - - - - - Returns a constraint that fails if the actual - value starts with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value ends with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value ends with the substring supplied as an argument. - - - - - Returns a constraint that fails if the actual - value ends with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value matches the regular expression supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value matches the regular expression supplied as an argument. - - - - - Returns a constraint that fails if the actual - value matches the pattern supplied as an argument. - - - - - Returns a constraint that tests whether the path provided - is the same as an expected path after canonicalization. - - - - - Returns a constraint that tests whether the path provided - is the same path or under an expected path after canonicalization. - - - - - Returns a constraint that tests whether the path provided - is the same path or under an expected path after canonicalization. - - - - - Returns a constraint that tests whether the actual value falls - within a specified range. - - - - - Returns a ConstraintExpression that negates any - following constraint. - - - - - Returns a ConstraintExpression that negates any - following constraint. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if all of them succeed. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if at least one of them succeeds. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if all of them fail. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the Length property of the object being tested. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the Count property of the object being tested. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the Message property of the object being tested. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the InnerException property of the object being tested. - - - - - Returns a constraint that tests for null - - - - - Returns a constraint that tests for True - - - - - Returns a constraint that tests for False - - - - - Returns a constraint that tests for a positive value - - - - - Returns a constraint that tests for a negative value - - - - - Returns a constraint that tests for NaN - - - - - Returns a constraint that tests for empty - - - - - Returns a constraint that tests whether a collection - contains all unique items. - - - - - Returns a constraint that tests whether an object graph is serializable in binary format. - - - - - Returns a constraint that tests whether an object graph is serializable in xml format. - - - - - Returns a constraint that tests whether a collection is ordered - - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. Works - identically to Assert.That. - - The actual value to test - A Constraint to be applied - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. Works - identically to Assert.That. - - The actual value to test - A Constraint to be applied - The message to be displayed in case of failure - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. Works - identically to Assert.That. - - The actual value to test - A Constraint to be applied - The message to be displayed in case of failure - Arguments to use in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . Works Identically to - . - - The evaluated condition - The message to display if the condition is false - Arguments to be used in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . Works Identically to - . - - The evaluated condition - The message to display if the condition is false - - - - Asserts that a condition is true. If the condition is false the method throws - an . Works Identically to . - - The evaluated condition - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - A Constraint expression to be applied - An ActualValueDelegate returning the value to be tested - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - A Constraint expression to be applied - An ActualValueDelegate returning the value to be tested - The message that will be displayed on failure - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - An ActualValueDelegate returning the value to be tested - A Constraint expression to be applied - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Apply a constraint to a referenced value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - The actual value to test - A Constraint to be applied - - - - Apply a constraint to a referenced value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - The actual value to test - A Constraint to be applied - The message that will be displayed on failure - - - - Apply a constraint to a referenced value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - The actual value to test - A Constraint to be applied - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that the code represented by a delegate throws an exception - that satisfies the constraint provided. - - A TestDelegate to be executed - A ThrowsConstraint used in the test - - - - Returns a ListMapper based on a collection. - - The original collection - - - - - Provides static methods to express the assumptions - that must be met for a test to give a meaningful - result. If an assumption is not met, the test - should produce an inconclusive result. - - - - - The Equals method throws an AssertionException. This is done - to make sure there is no mistake by calling this function. - - - - - - - override the default ReferenceEquals to throw an AssertionException. This - implementation makes sure there is no mistake in calling this function - as part of Assert. - - - - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an InconclusiveException on failure. - - A Constraint expression to be applied - The actual value to test - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an InconclusiveException on failure. - - A Constraint expression to be applied - The actual value to test - The message that will be displayed on failure - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an InconclusiveException on failure. - - A Constraint expression to be applied - The actual value to test - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display if the condition is false - Arguments to be used in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display if the condition is false - - - - Asserts that a condition is true. If the condition is false the - method throws an . - - The evaluated condition - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an InconclusiveException on failure. - - A Constraint expression to be applied - An ActualValueDelegate returning the value to be tested - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an InconclusiveException on failure. - - A Constraint expression to be applied - An ActualValueDelegate returning the value to be tested - The message that will be displayed on failure - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an InconclusiveException on failure. - - An ActualValueDelegate returning the value to be tested - A Constraint expression to be applied - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Apply a constraint to a referenced value, succeeding if the constraint - is satisfied and throwing an InconclusiveException on failure. - - A Constraint expression to be applied - The actual value to test - - - - Apply a constraint to a referenced value, succeeding if the constraint - is satisfied and throwing an InconclusiveException on failure. - - A Constraint expression to be applied - The actual value to test - The message that will be displayed on failure - - - - Apply a constraint to a referenced value, succeeding if the constraint - is satisfied and throwing an InconclusiveException on failure. - - A Constraint expression to be applied - The actual value to test - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that the code represented by a delegate throws an exception - that satisfies the constraint provided. - - A TestDelegate to be executed - A ThrowsConstraint used in the test - - - - Waits for pending asynchronous operations to complete, if appropriate, - and returns a proper result of the invocation by unwrapping task results - - The raw result of the method invocation - The unwrapped result, if necessary - - - - A set of Assert methods operationg on one or more collections - - - - - The Equals method throws an AssertionException. This is done - to make sure there is no mistake by calling this function. - - - - - - - override the default ReferenceEquals to throw an AssertionException. This - implementation makes sure there is no mistake in calling this function - as part of Assert. - - - - - - - Asserts that all items contained in collection are of the type specified by expectedType. - - IEnumerable containing objects to be considered - System.Type that all objects in collection must be instances of - - - - Asserts that all items contained in collection are of the type specified by expectedType. - - IEnumerable containing objects to be considered - System.Type that all objects in collection must be instances of - The message that will be displayed on failure - - - - Asserts that all items contained in collection are of the type specified by expectedType. - - IEnumerable containing objects to be considered - System.Type that all objects in collection must be instances of - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that all items contained in collection are not equal to null. - - IEnumerable containing objects to be considered - - - - Asserts that all items contained in collection are not equal to null. - - IEnumerable containing objects to be considered - The message that will be displayed on failure - - - - Asserts that all items contained in collection are not equal to null. - - IEnumerable of objects to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Ensures that every object contained in collection exists within the collection - once and only once. - - IEnumerable of objects to be considered - - - - Ensures that every object contained in collection exists within the collection - once and only once. - - IEnumerable of objects to be considered - The message that will be displayed on failure - - - - Ensures that every object contained in collection exists within the collection - once and only once. - - IEnumerable of objects to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that expected and actual are exactly equal. The collections must have the same count, - and contain the exact same objects in the same order. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - - - - Asserts that expected and actual are exactly equal. The collections must have the same count, - and contain the exact same objects in the same order. - If comparer is not null then it will be used to compare the objects. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The IComparer to use in comparing objects from each IEnumerable - - - - Asserts that expected and actual are exactly equal. The collections must have the same count, - and contain the exact same objects in the same order. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - - - - Asserts that expected and actual are exactly equal. The collections must have the same count, - and contain the exact same objects in the same order. - If comparer is not null then it will be used to compare the objects. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The IComparer to use in comparing objects from each IEnumerable - The message that will be displayed on failure - - - - Asserts that expected and actual are exactly equal. The collections must have the same count, - and contain the exact same objects in the same order. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that expected and actual are exactly equal. The collections must have the same count, - and contain the exact same objects in the same order. - If comparer is not null then it will be used to compare the objects. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The IComparer to use in comparing objects from each IEnumerable - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - - - - Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - - - - Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that expected and actual are not exactly equal. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - - - - Asserts that expected and actual are not exactly equal. - If comparer is not null then it will be used to compare the objects. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The IComparer to use in comparing objects from each IEnumerable - - - - Asserts that expected and actual are not exactly equal. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - - - - Asserts that expected and actual are not exactly equal. - If comparer is not null then it will be used to compare the objects. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The IComparer to use in comparing objects from each IEnumerable - The message that will be displayed on failure - - - - Asserts that expected and actual are not exactly equal. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that expected and actual are not exactly equal. - If comparer is not null then it will be used to compare the objects. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The IComparer to use in comparing objects from each IEnumerable - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that expected and actual are not equivalent. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - - - - Asserts that expected and actual are not equivalent. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - - - - Asserts that expected and actual are not equivalent. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that collection contains actual as an item. - - IEnumerable of objects to be considered - Object to be found within collection - - - - Asserts that collection contains actual as an item. - - IEnumerable of objects to be considered - Object to be found within collection - The message that will be displayed on failure - - - - Asserts that collection contains actual as an item. - - IEnumerable of objects to be considered - Object to be found within collection - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that collection does not contain actual as an item. - - IEnumerable of objects to be considered - Object that cannot exist within collection - - - - Asserts that collection does not contain actual as an item. - - IEnumerable of objects to be considered - Object that cannot exist within collection - The message that will be displayed on failure - - - - Asserts that collection does not contain actual as an item. - - IEnumerable of objects to be considered - Object that cannot exist within collection - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that the superset does not contain the subset - - The IEnumerable subset to be considered - The IEnumerable superset to be considered - - - - Asserts that the superset does not contain the subset - - The IEnumerable subset to be considered - The IEnumerable superset to be considered - The message that will be displayed on failure - - - - Asserts that the superset does not contain the subset - - The IEnumerable subset to be considered - The IEnumerable superset to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that the superset contains the subset. - - The IEnumerable subset to be considered - The IEnumerable superset to be considered - - - - Asserts that the superset contains the subset. - - The IEnumerable subset to be considered - The IEnumerable superset to be considered - The message that will be displayed on failure - - - - Asserts that the superset contains the subset. - - The IEnumerable subset to be considered - The IEnumerable superset to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing IEnumerable - The message to be displayed on failure - Arguments to be used in formatting the message - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing IEnumerable - The message to be displayed on failure - - - - Assert that an array,list or other collection is empty - - An array, list or other collection implementing IEnumerable - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing IEnumerable - The message to be displayed on failure - Arguments to be used in formatting the message - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing IEnumerable - The message to be displayed on failure - - - - Assert that an array,list or other collection is empty - - An array, list or other collection implementing IEnumerable - - - - Assert that an array, list or other collection is ordered - - An array, list or other collection implementing IEnumerable - The message to be displayed on failure - Arguments to be used in formatting the message - - - - Assert that an array, list or other collection is ordered - - An array, list or other collection implementing IEnumerable - The message to be displayed on failure - - - - Assert that an array, list or other collection is ordered - - An array, list or other collection implementing IEnumerable - - - - Assert that an array, list or other collection is ordered - - An array, list or other collection implementing IEnumerable - A custom comparer to perform the comparisons - The message to be displayed on failure - Arguments to be used in formatting the message - - - - Assert that an array, list or other collection is ordered - - An array, list or other collection implementing IEnumerable - A custom comparer to perform the comparisons - The message to be displayed on failure - - - - Assert that an array, list or other collection is ordered - - An array, list or other collection implementing IEnumerable - A custom comparer to perform the comparisons - - - - Helper class with properties and methods that supply - a number of constraints used in Asserts. - - - - - Returns a new CollectionContainsConstraint checking for the - presence of a particular object in the collection. - - - - - Returns a constraint that succeeds if the actual - value contains the substring supplied as an argument. - - - - - Summary description for DirectoryAssert - - - - - The Equals method throws an AssertionException. This is done - to make sure there is no mistake by calling this function. - - - - - - - override the default ReferenceEquals to throw an AssertionException. This - implementation makes sure there is no mistake in calling this function - as part of Assert. - - - - - - - We don't actually want any instances of this object, but some people - like to inherit from it to add other static methods. Hence, the - protected constructor disallows any instances of this object. - - - - - Verifies that two directories are equal. Two directories are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A directory containing the value that is expected - A directory containing the actual value - The message to display if directories are not equal - Arguments to be used in formatting the message - - - - Verifies that two directories are equal. Two directories are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A directory containing the value that is expected - A directory containing the actual value - The message to display if directories are not equal - - - - Verifies that two directories are equal. Two directories are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A directory containing the value that is expected - A directory containing the actual value - - - - Verifies that two directories are equal. Two directories are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A directory path string containing the value that is expected - A directory path string containing the actual value - The message to display if directories are not equal - Arguments to be used in formatting the message - - - - Verifies that two directories are equal. Two directories are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A directory path string containing the value that is expected - A directory path string containing the actual value - The message to display if directories are not equal - - - - Verifies that two directories are equal. Two directories are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A directory path string containing the value that is expected - A directory path string containing the actual value - - - - Asserts that two directories are not equal. If they are equal - an is thrown. - - A directory containing the value that is expected - A directory containing the actual value - The message to display if directories are not equal - Arguments to be used in formatting the message - - - - Asserts that two directories are not equal. If they are equal - an is thrown. - - A directory containing the value that is expected - A directory containing the actual value - The message to display if directories are not equal - - - - Asserts that two directories are not equal. If they are equal - an is thrown. - - A directory containing the value that is expected - A directory containing the actual value - - - - Asserts that two directories are not equal. If they are equal - an is thrown. - - A directory path string containing the value that is expected - A directory path string containing the actual value - The message to display if directories are equal - Arguments to be used in formatting the message - - - - Asserts that two directories are not equal. If they are equal - an is thrown. - - A directory path string containing the value that is expected - A directory path string containing the actual value - The message to display if directories are equal - - - - Asserts that two directories are not equal. If they are equal - an is thrown. - - A directory path string containing the value that is expected - A directory path string containing the actual value - - - - Asserts that the directory is empty. If it is not empty - an is thrown. - - A directory to search - The message to display if directories are not equal - Arguments to be used in formatting the message - - - - Asserts that the directory is empty. If it is not empty - an is thrown. - - A directory to search - The message to display if directories are not equal - - - - Asserts that the directory is empty. If it is not empty - an is thrown. - - A directory to search - - - - Asserts that the directory is empty. If it is not empty - an is thrown. - - A directory to search - The message to display if directories are not equal - Arguments to be used in formatting the message - - - - Asserts that the directory is empty. If it is not empty - an is thrown. - - A directory to search - The message to display if directories are not equal - - - - Asserts that the directory is empty. If it is not empty - an is thrown. - - A directory to search - - - - Asserts that the directory is not empty. If it is empty - an is thrown. - - A directory to search - The message to display if directories are not equal - Arguments to be used in formatting the message - - - - Asserts that the directory is not empty. If it is empty - an is thrown. - - A directory to search - The message to display if directories are not equal - - - - Asserts that the directory is not empty. If it is empty - an is thrown. - - A directory to search - - - - Asserts that the directory is not empty. If it is empty - an is thrown. - - A directory to search - The message to display if directories are not equal - Arguments to be used in formatting the message - - - - Asserts that the directory is not empty. If it is empty - an is thrown. - - A directory to search - The message to display if directories are not equal - - - - Asserts that the directory is not empty. If it is empty - an is thrown. - - A directory to search - - - - Asserts that path contains actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - The message to display if directory is not within the path - Arguments to be used in formatting the message - - - - Asserts that path contains actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - The message to display if directory is not within the path - - - - Asserts that path contains actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - - - - Asserts that path contains actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - The message to display if directory is not within the path - Arguments to be used in formatting the message - - - - Asserts that path contains actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - The message to display if directory is not within the path - - - - Asserts that path contains actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - - - - Asserts that path does not contain actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - The message to display if directory is not within the path - Arguments to be used in formatting the message - - - - Asserts that path does not contain actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - The message to display if directory is not within the path - - - - Asserts that path does not contain actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - - - - Asserts that path does not contain actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - The message to display if directory is not within the path - Arguments to be used in formatting the message - - - - Asserts that path does not contain actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - The message to display if directory is not within the path - - - - Asserts that path does not contain actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - - - - Summary description for FileAssert. - - - - - The Equals method throws an AssertionException. This is done - to make sure there is no mistake by calling this function. - - - - - - - override the default ReferenceEquals to throw an AssertionException. This - implementation makes sure there is no mistake in calling this function - as part of Assert. - - - - - - - We don't actually want any instances of this object, but some people - like to inherit from it to add other static methods. Hence, the - protected constructor disallows any instances of this object. - - - - - Verifies that two Streams are equal. Two Streams are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - The expected Stream - The actual Stream - The message to display if Streams are not equal - Arguments to be used in formatting the message - - - - Verifies that two Streams are equal. Two Streams are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - The expected Stream - The actual Stream - The message to display if objects are not equal - - - - Verifies that two Streams are equal. Two Streams are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - The expected Stream - The actual Stream - - - - Verifies that two files are equal. Two files are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A file containing the value that is expected - A file containing the actual value - The message to display if Streams are not equal - Arguments to be used in formatting the message - - - - Verifies that two files are equal. Two files are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A file containing the value that is expected - A file containing the actual value - The message to display if objects are not equal - - - - Verifies that two files are equal. Two files are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A file containing the value that is expected - A file containing the actual value - - - - Verifies that two files are equal. Two files are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - The path to a file containing the value that is expected - The path to a file containing the actual value - The message to display if Streams are not equal - Arguments to be used in formatting the message - - - - Verifies that two files are equal. Two files are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - The path to a file containing the value that is expected - The path to a file containing the actual value - The message to display if objects are not equal - - - - Verifies that two files are equal. Two files are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - The path to a file containing the value that is expected - The path to a file containing the actual value - - - - Asserts that two Streams are not equal. If they are equal - an is thrown. - - The expected Stream - The actual Stream - The message to be displayed when the two Stream are the same. - Arguments to be used in formatting the message - - - - Asserts that two Streams are not equal. If they are equal - an is thrown. - - The expected Stream - The actual Stream - The message to be displayed when the Streams are the same. - - - - Asserts that two Streams are not equal. If they are equal - an is thrown. - - The expected Stream - The actual Stream - - - - Asserts that two files are not equal. If they are equal - an is thrown. - - A file containing the value that is expected - A file containing the actual value - The message to display if Streams are not equal - Arguments to be used in formatting the message - - - - Asserts that two files are not equal. If they are equal - an is thrown. - - A file containing the value that is expected - A file containing the actual value - The message to display if objects are not equal - - - - Asserts that two files are not equal. If they are equal - an is thrown. - - A file containing the value that is expected - A file containing the actual value - - - - Asserts that two files are not equal. If they are equal - an is thrown. - - The path to a file containing the value that is expected - The path to a file containing the actual value - The message to display if Streams are not equal - Arguments to be used in formatting the message - - - - Asserts that two files are not equal. If they are equal - an is thrown. - - The path to a file containing the value that is expected - The path to a file containing the actual value - The message to display if objects are not equal - - - - Asserts that two files are not equal. If they are equal - an is thrown. - - The path to a file containing the value that is expected - The path to a file containing the actual value - - - - GlobalSettings is a place for setting default values used - by the framework in performing asserts. - - - - - Default tolerance for floating point equality - - - - - Class used to guard against unexpected argument values - by throwing an appropriate exception. - - - - - Throws an exception if an argument is null - - The value to be tested - The name of the argument - - - - Throws an exception if a string argument is null or empty - - The value to be tested - The name of the argument - - - - Helper class with properties and methods that supply - a number of constraints used in Asserts. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding only if a specified number of them succeed. - - - - - Returns a new PropertyConstraintExpression, which will either - test for the existence of the named property on the object - being tested or apply any following constraint to that property. - - - - - Returns a new AttributeConstraint checking for the - presence of a particular attribute on an object. - - - - - Returns a new AttributeConstraint checking for the - presence of a particular attribute on an object. - - - - - Returns a new CollectionContainsConstraint checking for the - presence of a particular object in the collection. - - - - - Returns a ConstraintExpression that negates any - following constraint. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if all of them succeed. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if at least one of them succeeds. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if all of them fail. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the Length property of the object being tested. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the Count property of the object being tested. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the Message property of the object being tested. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the InnerException property of the object being tested. - - - - - Interface implemented by a user fixture in order to - validate any expected exceptions. It is only called - for test methods marked with the ExpectedException - attribute. - - - - - Method to handle an expected exception - - The exception to be handled - - - - Helper class with properties and methods that supply - a number of constraints used in Asserts. - - - - - Returns a constraint that tests two items for equality - - - - - Returns a constraint that tests that two references are the same object - - - - - Returns a constraint that tests whether the - actual value is greater than the suppled argument - - - - - Returns a constraint that tests whether the - actual value is greater than or equal to the suppled argument - - - - - Returns a constraint that tests whether the - actual value is greater than or equal to the suppled argument - - - - - Returns a constraint that tests whether the - actual value is less than the suppled argument - - - - - Returns a constraint that tests whether the - actual value is less than or equal to the suppled argument - - - - - Returns a constraint that tests whether the - actual value is less than or equal to the suppled argument - - - - - Returns a constraint that tests whether the actual - value is of the exact type supplied as an argument. - - - - - Returns a constraint that tests whether the actual - value is of the exact type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is a collection containing the same elements as the - collection supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is a subset of the collection supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value contains the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value starts with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value ends with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value matches the regular expression supplied as an argument. - - - - - Returns a constraint that tests whether the path provided - is the same as an expected path after canonicalization. - - - - - Returns a constraint that tests whether the path provided - is under an expected path after canonicalization. - - - - - Returns a constraint that tests whether the path provided - is the same path or under an expected path after canonicalization. - - - - - Returns a constraint that tests whether the actual value falls - within a specified range. - - - - - Returns a ConstraintExpression that negates any - following constraint. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if all of them succeed. - - - - - Returns a constraint that tests for null - - - - - Returns a constraint that tests for True - - - - - Returns a constraint that tests for False - - - - - Returns a constraint that tests for a positive value - - - - - Returns a constraint that tests for a negative value - - - - - Returns a constraint that tests for NaN - - - - - Returns a constraint that tests for empty - - - - - Returns a constraint that tests whether a collection - contains all unique items. - - - - - Returns a constraint that tests whether an object graph is serializable in binary format. - - - - - Returns a constraint that tests whether an object graph is serializable in xml format. - - - - - Returns a constraint that tests whether a collection is ordered - - - - - The ITestCaseData interface is implemented by a class - that is able to return complete testcases for use by - a parameterized test method. - - NOTE: This interface is used in both the framework - and the core, even though that results in two different - types. However, sharing the source code guarantees that - the various implementations will be compatible and that - the core is able to reflect successfully over the - framework implementations of ITestCaseData. - - - - - Gets the argument list to be provided to the test - - - - - Gets the expected result - - - - - Indicates whether a result has been specified. - This is necessary because the result may be - null, so it's value cannot be checked. - - - - - Gets the expected exception Type - - - - - Gets the FullName of the expected exception - - - - - Gets the name to be used for the test - - - - - Gets the description of the test - - - - - Gets a value indicating whether this is ignored. - - true if ignored; otherwise, false. - - - - Gets a value indicating whether this is explicit. - - true if explicit; otherwise, false. - - - - Gets the ignore reason. - - The ignore reason. - - - - The Iz class is a synonym for Is intended for use in VB, - which regards Is as a keyword. - - - - - The List class is a helper class with properties and methods - that supply a number of constraints used with lists and collections. - - - - - List.Map returns a ListMapper, which can be used to map - the original collection to another collection. - - - - - - - ListMapper is used to transform a collection used as an actual argument - producing another collection to be used in the assertion. - - - - - Construct a ListMapper based on a collection - - The collection to be transformed - - - - Produces a collection containing all the values of a property - - The collection of property values - - - - - Randomizer returns a set of random values in a repeatable - way, to allow re-running of tests if necessary. - - - - - Get a randomizer for a particular member, returning - one that has already been created if it exists. - This ensures that the same values are generated - each time the tests are reloaded. - - - - - Get a randomizer for a particular parameter, returning - one that has already been created if it exists. - This ensures that the same values are generated - each time the tests are reloaded. - - - - - Construct a randomizer using a random seed - - - - - Construct a randomizer using a specified seed - - - - - Return an array of random doubles between 0.0 and 1.0. - - - - - - - Return an array of random doubles with values in a specified range. - - - - - Return an array of random ints with values in a specified range. - - - - - Get a random seed for use in creating a randomizer. - - - - - The SpecialValue enum is used to represent TestCase arguments - that cannot be used as arguments to an Attribute. - - - - - Null represents a null value, which cannot be used as an - argument to an attribute under .NET 1.x - - - - - Basic Asserts on strings. - - - - - The Equals method throws an AssertionException. This is done - to make sure there is no mistake by calling this function. - - - - - - - override the default ReferenceEquals to throw an AssertionException. This - implementation makes sure there is no mistake in calling this function - as part of Assert. - - - - - - - Asserts that a string is found within another string. - - The expected string - The string to be examined - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string is found within another string. - - The expected string - The string to be examined - The message to display in case of failure - - - - Asserts that a string is found within another string. - - The expected string - The string to be examined - - - - Asserts that a string is not found within another string. - - The expected string - The string to be examined - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string is found within another string. - - The expected string - The string to be examined - The message to display in case of failure - - - - Asserts that a string is found within another string. - - The expected string - The string to be examined - - - - Asserts that a string starts with another string. - - The expected string - The string to be examined - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string starts with another string. - - The expected string - The string to be examined - The message to display in case of failure - - - - Asserts that a string starts with another string. - - The expected string - The string to be examined - - - - Asserts that a string does not start with another string. - - The expected string - The string to be examined - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string does not start with another string. - - The expected string - The string to be examined - The message to display in case of failure - - - - Asserts that a string does not start with another string. - - The expected string - The string to be examined - - - - Asserts that a string ends with another string. - - The expected string - The string to be examined - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string ends with another string. - - The expected string - The string to be examined - The message to display in case of failure - - - - Asserts that a string ends with another string. - - The expected string - The string to be examined - - - - Asserts that a string does not end with another string. - - The expected string - The string to be examined - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string does not end with another string. - - The expected string - The string to be examined - The message to display in case of failure - - - - Asserts that a string does not end with another string. - - The expected string - The string to be examined - - - - Asserts that two strings are equal, without regard to case. - - The expected string - The actual string - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that two strings are equal, without regard to case. - - The expected string - The actual string - The message to display in case of failure - - - - Asserts that two strings are equal, without regard to case. - - The expected string - The actual string - - - - Asserts that two strings are not equal, without regard to case. - - The expected string - The actual string - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that two strings are Notequal, without regard to case. - - The expected string - The actual string - The message to display in case of failure - - - - Asserts that two strings are not equal, without regard to case. - - The expected string - The actual string - - - - Asserts that a string matches an expected regular expression pattern. - - The regex pattern to be matched - The actual string - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string matches an expected regular expression pattern. - - The regex pattern to be matched - The actual string - The message to display in case of failure - - - - Asserts that a string matches an expected regular expression pattern. - - The regex pattern to be matched - The actual string - - - - Asserts that a string does not match an expected regular expression pattern. - - The regex pattern to be used - The actual string - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string does not match an expected regular expression pattern. - - The regex pattern to be used - The actual string - The message to display in case of failure - - - - Asserts that a string does not match an expected regular expression pattern. - - The regex pattern to be used - The actual string - - - - The TestCaseData class represents a set of arguments - and other parameter info to be used for a parameterized - test case. It provides a number of instance modifiers - for use in initializing the test case. - - Note: Instance modifiers are getters that return - the same instance after modifying it's state. - - - - - The argument list to be provided to the test - - - - - The expected result to be returned - - - - - Set to true if this has an expected result - - - - - The expected exception Type - - - - - The FullName of the expected exception - - - - - The name to be used for the test - - - - - The description of the test - - - - - A dictionary of properties, used to add information - to tests without requiring the class to change. - - - - - If true, indicates that the test case is to be ignored - - - - - If true, indicates that the test case is marked explicit - - - - - The reason for ignoring a test case - - - - - Initializes a new instance of the class. - - The arguments. - - - - Initializes a new instance of the class. - - The argument. - - - - Initializes a new instance of the class. - - The first argument. - The second argument. - - - - Initializes a new instance of the class. - - The first argument. - The second argument. - The third argument. - - - - Sets the expected result for the test - - The expected result - A modified TestCaseData - - - - Sets the expected exception type for the test - - Type of the expected exception. - The modified TestCaseData instance - - - - Sets the expected exception type for the test - - FullName of the expected exception. - The modified TestCaseData instance - - - - Sets the name of the test case - - The modified TestCaseData instance - - - - Sets the description for the test case - being constructed. - - The description. - The modified TestCaseData instance. - - - - Applies a category to the test - - - - - - - Applies a named property to the test - - - - - - - - Applies a named property to the test - - - - - - - - Applies a named property to the test - - - - - - - - Ignores this TestCase. - - - - - - Ignores this TestCase, specifying the reason. - - The reason. - - - - - Marks this TestCase as Explicit - - - - - - Marks this TestCase as Explicit, specifying the reason. - - The reason. - - - - - Gets the argument list to be provided to the test - - - - - Gets the expected result - - - - - Returns true if the result has been set - - - - - Gets the expected exception Type - - - - - Gets the FullName of the expected exception - - - - - Gets the name to be used for the test - - - - - Gets the description of the test - - - - - Gets a value indicating whether this is ignored. - - true if ignored; otherwise, false. - - - - Gets a value indicating whether this is explicit. - - true if explicit; otherwise, false. - - - - Gets the ignore reason. - - The ignore reason. - - - - Gets a list of categories associated with this test. - - - - - Gets the property dictionary for this test - - - - - Provide the context information of the current test - - - - - Constructs a TestContext using the provided context dictionary - - A context dictionary - - - - Get the current test context. This is created - as needed. The user may save the context for - use within a test, but it should not be used - outside the test for which it is created. - - - - - Gets a TestAdapter representing the currently executing test in this context. - - - - - Gets a ResultAdapter representing the current result for the test - executing in this context. - - - - - Gets the directory containing the current test assembly. - - - - - Gets the directory to be used for outputing files created - by this test run. - - - - - TestAdapter adapts a Test for consumption by - the user test code. - - - - - Constructs a TestAdapter for this context - - The context dictionary - - - - The name of the test. - - - - - The FullName of the test - - - - - The properties of the test. - - - - - ResultAdapter adapts a TestResult for consumption by - the user test code. - - - - - Construct a ResultAdapter for a context - - The context holding the result - - - - The TestState of current test. This maps to the ResultState - used in nunit.core and is subject to change in the future. - - - - - The TestStatus of current test. This enum will be used - in future versions of NUnit and so is to be preferred - to the TestState value. - - - - - Provides details about a test - - - - - Creates an instance of TestDetails - - The fixture that the test is a member of, if available. - The method that implements the test, if available. - The full name of the test. - A string representing the type of test, e.g. "Test Case". - Indicates if the test represents a suite of tests. - - - - The fixture that the test is a member of, if available. - - - - - The method that implements the test, if available. - - - - - The full name of the test. - - - - - A string representing the type of test, e.g. "Test Case". - - - - - Indicates if the test represents a suite of tests. - - - - - The ResultState enum indicates the result of running a test - - - - - The result is inconclusive - - - - - The test was not runnable. - - - - - The test has been skipped. - - - - - The test has been ignored. - - - - - The test succeeded - - - - - The test failed - - - - - The test encountered an unexpected exception - - - - - The test was cancelled by the user - - - - - The TestStatus enum indicates the result of running a test - - - - - The test was inconclusive - - - - - The test has skipped - - - - - The test succeeded - - - - - The test failed - - - - - Helper class with static methods used to supply constraints - that operate on strings. - - - - - Returns a constraint that succeeds if the actual - value contains the substring supplied as an argument. - - - - - Returns a constraint that fails if the actual - value contains the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value starts with the substring supplied as an argument. - - - - - Returns a constraint that fails if the actual - value starts with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value ends with the substring supplied as an argument. - - - - - Returns a constraint that fails if the actual - value ends with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value matches the Regex pattern supplied as an argument. - - - - - Returns a constraint that fails if the actual - value matches the pattern supplied as an argument. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if all of them succeed. - - - - - TextMessageWriter writes constraint descriptions and messages - in displayable form as a text stream. It tailors the display - of individual message components to form the standard message - format of NUnit assertion failure messages. - - - - - MessageWriter is the abstract base for classes that write - constraint descriptions and messages in some form. The - class has separate methods for writing various components - of a message, allowing implementations to tailor the - presentation as needed. - - - - - Construct a MessageWriter given a culture - - - - - Method to write single line message with optional args, usually - written to precede the general failure message. - - The message to be written - Any arguments used in formatting the message - - - - Method to write single line message with optional args, usually - written to precede the general failure message, at a givel - indentation level. - - The indentation level of the message - The message to be written - Any arguments used in formatting the message - - - - Display Expected and Actual lines for a constraint. This - is called by MessageWriter's default implementation of - WriteMessageTo and provides the generic two-line display. - - The constraint that failed - - - - Display Expected and Actual lines for given values. This - method may be called by constraints that need more control over - the display of actual and expected values than is provided - by the default implementation. - - The expected value - The actual value causing the failure - - - - Display Expected and Actual lines for given values, including - a tolerance value on the Expected line. - - The expected value - The actual value causing the failure - The tolerance within which the test was made - - - - Display the expected and actual string values on separate lines. - If the mismatch parameter is >=0, an additional line is displayed - line containing a caret that points to the mismatch point. - - The expected string value - The actual string value - The point at which the strings don't match or -1 - If true, case is ignored in locating the point where the strings differ - If true, the strings should be clipped to fit the line - - - - Writes the text for a connector. - - The connector. - - - - Writes the text for a predicate. - - The predicate. - - - - Writes the text for an expected value. - - The expected value. - - - - Writes the text for a modifier - - The modifier. - - - - Writes the text for an actual value. - - The actual value. - - - - Writes the text for a generalized value. - - The value. - - - - Writes the text for a collection value, - starting at a particular point, to a max length - - The collection containing elements to write. - The starting point of the elements to write - The maximum number of elements to write - - - - Abstract method to get the max line length - - - - - Prefix used for the expected value line of a message - - - - - Prefix used for the actual value line of a message - - - - - Length of a message prefix - - - - - Construct a TextMessageWriter - - - - - Construct a TextMessageWriter, specifying a user message - and optional formatting arguments. - - - - - - - Method to write single line message with optional args, usually - written to precede the general failure message, at a givel - indentation level. - - The indentation level of the message - The message to be written - Any arguments used in formatting the message - - - - Display Expected and Actual lines for a constraint. This - is called by MessageWriter's default implementation of - WriteMessageTo and provides the generic two-line display. - - The constraint that failed - - - - Display Expected and Actual lines for given values. This - method may be called by constraints that need more control over - the display of actual and expected values than is provided - by the default implementation. - - The expected value - The actual value causing the failure - - - - Display Expected and Actual lines for given values, including - a tolerance value on the expected line. - - The expected value - The actual value causing the failure - The tolerance within which the test was made - - - - Display the expected and actual string values on separate lines. - If the mismatch parameter is >=0, an additional line is displayed - line containing a caret that points to the mismatch point. - - The expected string value - The actual string value - The point at which the strings don't match or -1 - If true, case is ignored in string comparisons - If true, clip the strings to fit the max line length - - - - Writes the text for a connector. - - The connector. - - - - Writes the text for a predicate. - - The predicate. - - - - Write the text for a modifier. - - The modifier. - - - - Writes the text for an expected value. - - The expected value. - - - - Writes the text for an actual value. - - The actual value. - - - - Writes the text for a generalized value. - - The value. - - - - Writes the text for a collection value, - starting at a particular point, to a max length - - The collection containing elements to write. - The starting point of the elements to write - The maximum number of elements to write - - - - Write the generic 'Expected' line for a constraint - - The constraint that failed - - - - Write the generic 'Expected' line for a given value - - The expected value - - - - Write the generic 'Expected' line for a given value - and tolerance. - - The expected value - The tolerance within which the test was made - - - - Write the generic 'Actual' line for a constraint - - The constraint for which the actual value is to be written - - - - Write the generic 'Actual' line for a given value - - The actual value causing a failure - - - - Gets or sets the maximum line length for this writer - - - - - Helper class with properties and methods that supply - constraints that operate on exceptions. - - - - - Creates a constraint specifying the exact type of exception expected - - - - - Creates a constraint specifying the exact type of exception expected - - - - - Creates a constraint specifying the type of exception expected - - - - - Creates a constraint specifying the type of exception expected - - - - - Creates a constraint specifying an expected exception - - - - - Creates a constraint specifying an exception with a given InnerException - - - - - Creates a constraint specifying an expected TargetInvocationException - - - - - Creates a constraint specifying an expected TargetInvocationException - - - - - Creates a constraint specifying an expected TargetInvocationException - - - - - Creates a constraint specifying that no exception is thrown - - - - - Attribute used to apply a category to a test - - - - - The name of the category - - - - - Construct attribute for a given category based on - a name. The name may not contain the characters ',', - '+', '-' or '!'. However, this is not checked in the - constructor since it would cause an error to arise at - as the test was loaded without giving a clear indication - of where the problem is located. The error is handled - in NUnitFramework.cs by marking the test as not - runnable. - - The name of the category - - - - Protected constructor uses the Type name as the name - of the category. - - - - - The name of the category - - - - - Used to mark a field for use as a datapoint when executing a theory - within the same fixture that requires an argument of the field's Type. - - - - - Used to mark an array as containing a set of datapoints to be used - executing a theory within the same fixture that requires an argument - of the Type of the array elements. - - - - - Attribute used to provide descriptive text about a - test case or fixture. - - - - - Construct the attribute - - Text describing the test - - - - Gets the test description - - - - - Enumeration indicating how the expected message parameter is to be used - - - - Expect an exact match - - - Expect a message containing the parameter string - - - Match the regular expression provided as a parameter - - - Expect a message that starts with the parameter string - - - - ExpectedExceptionAttribute - - - - - - Constructor for a non-specific exception - - - - - Constructor for a given type of exception - - The type of the expected exception - - - - Constructor for a given exception name - - The full name of the expected exception - - - - Gets or sets the expected exception type - - - - - Gets or sets the full Type name of the expected exception - - - - - Gets or sets the expected message text - - - - - Gets or sets the user message displayed in case of failure - - - - - Gets or sets the type of match to be performed on the expected message - - - - - Gets the name of a method to be used as an exception handler - - - - - ExplicitAttribute marks a test or test fixture so that it will - only be run if explicitly executed from the gui or command line - or if it is included by use of a filter. The test will not be - run simply because an enclosing suite is run. - - - - - Default constructor - - - - - Constructor with a reason - - The reason test is marked explicit - - - - The reason test is marked explicit - - - - - Attribute used to mark a test that is to be ignored. - Ignored tests result in a warning message when the - tests are run. - - - - - Constructs the attribute without giving a reason - for ignoring the test. - - - - - Constructs the attribute giving a reason for ignoring the test - - The reason for ignoring the test - - - - The reason for ignoring a test - - - - - Abstract base for Attributes that are used to include tests - in the test run based on environmental settings. - - - - - Constructor with no included items specified, for use - with named property syntax. - - - - - Constructor taking one or more included items - - Comma-delimited list of included items - - - - Name of the item that is needed in order for - a test to run. Multiple itemss may be given, - separated by a comma. - - - - - Name of the item to be excluded. Multiple items - may be given, separated by a comma. - - - - - The reason for including or excluding the test - - - - - PlatformAttribute is used to mark a test fixture or an - individual method as applying to a particular platform only. - - - - - Constructor with no platforms specified, for use - with named property syntax. - - - - - Constructor taking one or more platforms - - Comma-deliminted list of platforms - - - - CultureAttribute is used to mark a test fixture or an - individual method as applying to a particular Culture only. - - - - - Constructor with no cultures specified, for use - with named property syntax. - - - - - Constructor taking one or more cultures - - Comma-deliminted list of cultures - - - - Marks a test to use a combinatorial join of any argument data - provided. NUnit will create a test case for every combination of - the arguments provided. This can result in a large number of test - cases and so should be used judiciously. This is the default join - type, so the attribute need not be used except as documentation. - - - - - PropertyAttribute is used to attach information to a test as a name/value pair.. - - - - - Construct a PropertyAttribute with a name and string value - - The name of the property - The property value - - - - Construct a PropertyAttribute with a name and int value - - The name of the property - The property value - - - - Construct a PropertyAttribute with a name and double value - - The name of the property - The property value - - - - Constructor for derived classes that set the - property dictionary directly. - - - - - Constructor for use by derived classes that use the - name of the type as the property name. Derived classes - must ensure that the Type of the property value is - a standard type supported by the BCL. Any custom - types will cause a serialization Exception when - in the client. - - - - - Gets the property dictionary for this attribute - - - - - Default constructor - - - - - Marks a test to use pairwise join of any argument data provided. - NUnit will attempt too excercise every pair of argument values at - least once, using as small a number of test cases as it can. With - only two arguments, this is the same as a combinatorial join. - - - - - Default constructor - - - - - Marks a test to use a sequential join of any argument data - provided. NUnit will use arguements for each parameter in - sequence, generating test cases up to the largest number - of argument values provided and using null for any arguments - for which it runs out of values. Normally, this should be - used with the same number of arguments for each parameter. - - - - - Default constructor - - - - - Summary description for MaxTimeAttribute. - - - - - Construct a MaxTimeAttribute, given a time in milliseconds. - - The maximum elapsed time in milliseconds - - - - RandomAttribute is used to supply a set of random values - to a single parameter of a parameterized test. - - - - - ValuesAttribute is used to provide literal arguments for - an individual parameter of a test. - - - - - Abstract base class for attributes that apply to parameters - and supply data for the parameter. - - - - - Gets the data to be provided to the specified parameter - - - - - The collection of data to be returned. Must - be set by any derived attribute classes. - We use an object[] so that the individual - elements may have their type changed in GetData - if necessary. - - - - - Construct with one argument - - - - - - Construct with two arguments - - - - - - - Construct with three arguments - - - - - - - - Construct with an array of arguments - - - - - - Get the collection of values to be used as arguments - - - - - Construct a set of doubles from 0.0 to 1.0, - specifying only the count. - - - - - - Construct a set of doubles from min to max - - - - - - - - Construct a set of ints from min to max - - - - - - - - Get the collection of values to be used as arguments - - - - - RangeAttribute is used to supply a range of values to an - individual parameter of a parameterized test. - - - - - Construct a range of ints using default step of 1 - - - - - - - Construct a range of ints specifying the step size - - - - - - - - Construct a range of longs - - - - - - - - Construct a range of doubles - - - - - - - - Construct a range of floats - - - - - - - - RepeatAttribute may be applied to test case in order - to run it multiple times. - - - - - Construct a RepeatAttribute - - The number of times to run the test - - - - RequiredAddinAttribute may be used to indicate the names of any addins - that must be present in order to run some or all of the tests in an - assembly. If the addin is not loaded, the entire assembly is marked - as NotRunnable. - - - - - Initializes a new instance of the class. - - The required addin. - - - - Gets the name of required addin. - - The required addin name. - - - - Summary description for SetCultureAttribute. - - - - - Construct given the name of a culture - - - - - - Summary description for SetUICultureAttribute. - - - - - Construct given the name of a culture - - - - - - SetUpAttribute is used in a TestFixture to identify a method - that is called immediately before each test is run. It is - also used in a SetUpFixture to identify the method that is - called once, before any of the subordinate tests are run. - - - - - Attribute used to mark a class that contains one-time SetUp - and/or TearDown methods that apply to all the tests in a - namespace or an assembly. - - - - - Attribute used to mark a static (shared in VB) property - that returns a list of tests. - - - - - Attribute used in a TestFixture to identify a method that is - called immediately after each test is run. It is also used - in a SetUpFixture to identify the method that is called once, - after all subordinate tests have run. In either case, the method - is guaranteed to be called, even if an exception is thrown. - - - - - Provide actions to execute before and after tests. - - - - - When implemented by an attribute, this interface implemented to provide actions to execute before and after tests. - - - - - Executed before each test is run - - Provides details about the test that is going to be run. - - - - Executed after each test is run - - Provides details about the test that has just been run. - - - - Provides the target for the action attribute - - The target for the action attribute - - - - Method called before each test - - Info about the test to be run - - - - Method called after each test - - Info about the test that was just run - - - - Gets or sets the ActionTargets for this attribute - - - - - Adding this attribute to a method within a - class makes the method callable from the NUnit test runner. There is a property - called Description which is optional which you can provide a more detailed test - description. This class cannot be inherited. - - - - [TestFixture] - public class Fixture - { - [Test] - public void MethodToTest() - {} - - [Test(Description = "more detailed description")] - publc void TestDescriptionMethod() - {} - } - - - - - - Descriptive text for this test - - - - - TestCaseAttribute is used to mark parameterized test cases - and provide them with their arguments. - - - - - Construct a TestCaseAttribute with a list of arguments. - This constructor is not CLS-Compliant - - - - - - Construct a TestCaseAttribute with a single argument - - - - - - Construct a TestCaseAttribute with a two arguments - - - - - - - Construct a TestCaseAttribute with a three arguments - - - - - - - - Gets the list of arguments to a test case - - - - - Gets or sets the expected result. Use - ExpectedResult by preference. - - The result. - - - - Gets or sets the expected result. - - The result. - - - - Gets a flag indicating whether an expected - result has been set. - - - - - Gets a list of categories associated with this test; - - - - - Gets or sets the category associated with this test. - May be a single category or a comma-separated list. - - - - - Gets or sets the expected exception. - - The expected exception. - - - - Gets or sets the name the expected exception. - - The expected name of the exception. - - - - Gets or sets the expected message of the expected exception - - The expected message of the exception. - - - - Gets or sets the type of match to be performed on the expected message - - - - - Gets or sets the description. - - The description. - - - - Gets or sets the name of the test. - - The name of the test. - - - - Gets or sets the ignored status of the test - - - - - Gets or sets the ignored status of the test - - - - - Gets or sets the explicit status of the test - - - - - Gets or sets the reason for not running the test - - - - - Gets or sets the reason for not running the test. - Set has the side effect of marking the test as ignored. - - The ignore reason. - - - - FactoryAttribute indicates the source to be used to - provide test cases for a test method. - - - - - Construct with the name of the data source, which must - be a property, field or method of the test class itself. - - An array of the names of the factories that will provide data - - - - Construct with a Type, which must implement IEnumerable - - The Type that will provide data - - - - Construct with a Type and name. - that don't support params arrays. - - The Type that will provide data - The name of the method, property or field that will provide data - - - - The name of a the method, property or fiend to be used as a source - - - - - A Type to be used as a source - - - - - Gets or sets the category associated with this test. - May be a single category or a comma-separated list. - - - - - [TestFixture] - public class ExampleClass - {} - - - - - Default constructor - - - - - Construct with a object[] representing a set of arguments. - In .NET 2.0, the arguments may later be separated into - type arguments and constructor arguments. - - - - - - Descriptive text for this fixture - - - - - Gets and sets the category for this fixture. - May be a comma-separated list of categories. - - - - - Gets a list of categories for this fixture - - - - - The arguments originally provided to the attribute - - - - - Gets or sets a value indicating whether this should be ignored. - - true if ignore; otherwise, false. - - - - Gets or sets the ignore reason. May set Ignored as a side effect. - - The ignore reason. - - - - Get or set the type arguments. If not set - explicitly, any leading arguments that are - Types are taken as type arguments. - - - - - Attribute used to identify a method that is - called before any tests in a fixture are run. - - - - - Attribute used to identify a method that is called after - all the tests in a fixture have run. The method is - guaranteed to be called, even if an exception is thrown. - - - - - Adding this attribute to a method within a - class makes the method callable from the NUnit test runner. There is a property - called Description which is optional which you can provide a more detailed test - description. This class cannot be inherited. - - - - [TestFixture] - public class Fixture - { - [Test] - public void MethodToTest() - {} - - [Test(Description = "more detailed description")] - publc void TestDescriptionMethod() - {} - } - - - - - - Used on a method, marks the test with a timeout value in milliseconds. - The test will be run in a separate thread and is cancelled if the timeout - is exceeded. Used on a method or assembly, sets the default timeout - for all contained test methods. - - - - - Construct a TimeoutAttribute given a time in milliseconds - - The timeout value in milliseconds - - - - Marks a test that must run in the STA, causing it - to run in a separate thread if necessary. - - On methods, you may also use STAThreadAttribute - to serve the same purpose. - - - - - Construct a RequiresSTAAttribute - - - - - Marks a test that must run in the MTA, causing it - to run in a separate thread if necessary. - - On methods, you may also use MTAThreadAttribute - to serve the same purpose. - - - - - Construct a RequiresMTAAttribute - - - - - Marks a test that must run on a separate thread. - - - - - Construct a RequiresThreadAttribute - - - - - Construct a RequiresThreadAttribute, specifying the apartment - - - - - ValueSourceAttribute indicates the source to be used to - provide data for one parameter of a test method. - - - - - Construct with the name of the factory - for use with languages - that don't support params arrays. - - The name of the data source to be used - - - - Construct with a Type and name - for use with languages - that don't support params arrays. - - The Type that will provide data - The name of the method, property or field that will provide data - - - - The name of a the method, property or fiend to be used as a source - - - - - A Type to be used as a source - - - - - AllItemsConstraint applies another constraint to each - item in a collection, succeeding if they all succeed. - - - - - Abstract base class used for prefixes - - - - - The Constraint class is the base of all built-in constraints - within NUnit. It provides the operator overloads used to combine - constraints. - - - - - The IConstraintExpression interface is implemented by all - complete and resolvable constraints and expressions. - - - - - Return the top-level constraint for this expression - - - - - - Static UnsetObject used to detect derived constraints - failing to set the actual value. - - - - - The actual value being tested against a constraint - - - - - The display name of this Constraint for use by ToString() - - - - - Argument fields used by ToString(); - - - - - The builder holding this constraint - - - - - Construct a constraint with no arguments - - - - - Construct a constraint with one argument - - - - - Construct a constraint with two arguments - - - - - Sets the ConstraintBuilder holding this constraint - - - - - Write the failure message to the MessageWriter provided - as an argument. The default implementation simply passes - the constraint and the actual value to the writer, which - then displays the constraint description and the value. - - Constraints that need to provide additional details, - such as where the error occured can override this. - - The MessageWriter on which to display the message - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Test whether the constraint is satisfied by an - ActualValueDelegate that returns the value to be tested. - The default implementation simply evaluates the delegate - but derived classes may override it to provide for delayed - processing. - - An - True for success, false for failure - - - - Test whether the constraint is satisfied by a given reference. - The default implementation simply dereferences the value but - derived classes may override it to provide for delayed processing. - - A reference to the value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a - MessageWriter. The default implementation simply writes - the raw value of actual, leaving it to the writer to - perform any formatting. - - The writer on which the actual value is displayed - - - - Default override of ToString returns the constraint DisplayName - followed by any arguments within angle brackets. - - - - - - Returns the string representation of this constraint - - - - - This operator creates a constraint that is satisfied only if both - argument constraints are satisfied. - - - - - This operator creates a constraint that is satisfied if either - of the argument constraints is satisfied. - - - - - This operator creates a constraint that is satisfied if the - argument constraint is not satisfied. - - - - - Returns a DelayedConstraint with the specified delay time. - - The delay in milliseconds. - - - - - Returns a DelayedConstraint with the specified delay time - and polling interval. - - The delay in milliseconds. - The interval at which to test the constraint. - - - - - The display name of this Constraint for use by ToString(). - The default value is the name of the constraint with - trailing "Constraint" removed. Derived classes may set - this to another name in their constructors. - - - - - Returns a ConstraintExpression by appending And - to the current constraint. - - - - - Returns a ConstraintExpression by appending And - to the current constraint. - - - - - Returns a ConstraintExpression by appending Or - to the current constraint. - - - - - Class used to detect any derived constraints - that fail to set the actual value in their - Matches override. - - - - - The base constraint - - - - - Construct given a base constraint - - - - - - Construct an AllItemsConstraint on top of an existing constraint - - - - - - Apply the item constraint to each item in the collection, - failing if any item fails. - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - AndConstraint succeeds only if both members succeed. - - - - - BinaryConstraint is the abstract base of all constraints - that combine two other constraints in some fashion. - - - - - The first constraint being combined - - - - - The second constraint being combined - - - - - Construct a BinaryConstraint from two other constraints - - The first constraint - The second constraint - - - - Create an AndConstraint from two other constraints - - The first constraint - The second constraint - - - - Apply both member constraints to an actual value, succeeding - succeeding only if both of them succeed. - - The actual value - True if the constraints both succeeded - - - - Write a description for this contraint to a MessageWriter - - The MessageWriter to receive the description - - - - Write the actual value for a failing constraint test to a - MessageWriter. The default implementation simply writes - the raw value of actual, leaving it to the writer to - perform any formatting. - - The writer on which the actual value is displayed - - - - AssignableFromConstraint is used to test that an object - can be assigned from a given Type. - - - - - TypeConstraint is the abstract base for constraints - that take a Type as their expected value. - - - - - The expected Type used by the constraint - - - - - Construct a TypeConstraint for a given Type - - - - - - Write the actual value for a failing constraint test to a - MessageWriter. TypeConstraints override this method to write - the name of the type. - - The writer on which the actual value is displayed - - - - Construct an AssignableFromConstraint for the type provided - - - - - - Test whether an object can be assigned from the specified type - - The object to be tested - True if the object can be assigned a value of the expected Type, otherwise false. - - - - Write a description of this constraint to a MessageWriter - - The MessageWriter to use - - - - AssignableToConstraint is used to test that an object - can be assigned to a given Type. - - - - - Construct an AssignableToConstraint for the type provided - - - - - - Test whether an object can be assigned to the specified type - - The object to be tested - True if the object can be assigned a value of the expected Type, otherwise false. - - - - Write a description of this constraint to a MessageWriter - - The MessageWriter to use - - - - AttributeConstraint tests that a specified attribute is present - on a Type or other provider and that the value of the attribute - satisfies some other constraint. - - - - - Constructs an AttributeConstraint for a specified attriute - Type and base constraint. - - - - - - - Determines whether the Type or other provider has the - expected attribute and if its value matches the - additional constraint specified. - - - - - Writes a description of the attribute to the specified writer. - - - - - Writes the actual value supplied to the specified writer. - - - - - Returns a string representation of the constraint. - - - - - AttributeExistsConstraint tests for the presence of a - specified attribute on a Type. - - - - - Constructs an AttributeExistsConstraint for a specific attribute Type - - - - - - Tests whether the object provides the expected attribute. - - A Type, MethodInfo, or other ICustomAttributeProvider - True if the expected attribute is present, otherwise false - - - - Writes the description of the constraint to the specified writer - - - - - BasicConstraint is the abstract base for constraints that - perform a simple comparison to a constant value. - - - - - Initializes a new instance of the class. - - The expected. - The description. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - BinarySerializableConstraint tests whether - an object is serializable in binary format. - - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a - MessageWriter. The default implementation simply writes - the raw value of actual, leaving it to the writer to - perform any formatting. - - The writer on which the actual value is displayed - - - - Returns the string representation - - - - - CollectionConstraint is the abstract base class for - constraints that operate on collections. - - - - - Construct an empty CollectionConstraint - - - - - Construct a CollectionConstraint - - - - - - Determines whether the specified enumerable is empty. - - The enumerable. - - true if the specified enumerable is empty; otherwise, false. - - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Protected method to be implemented by derived classes - - - - - - - CollectionContainsConstraint is used to test whether a collection - contains an expected object as a member. - - - - - CollectionItemsEqualConstraint is the abstract base class for all - collection constraints that apply some notion of item equality - as a part of their operation. - - - - - Construct an empty CollectionConstraint - - - - - Construct a CollectionConstraint - - - - - - Flag the constraint to use the supplied EqualityAdapter. - NOTE: For internal use only. - - The EqualityAdapter to use. - Self. - - - - Flag the constraint to use the supplied IComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied Comparison object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IEqualityComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IEqualityComparer object. - - The IComparer object to use. - Self. - - - - Compares two collection members for equality - - - - - Return a new CollectionTally for use in making tests - - The collection to be included in the tally - - - - Flag the constraint to ignore case and return self. - - - - - Construct a CollectionContainsConstraint - - - - - - Test whether the expected item is contained in the collection - - - - - - - Write a descripton of the constraint to a MessageWriter - - - - - - CollectionEquivalentCOnstraint is used to determine whether two - collections are equivalent. - - - - - Construct a CollectionEquivalentConstraint - - - - - - Test whether two collections are equivalent - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - CollectionOrderedConstraint is used to test whether a collection is ordered. - - - - - Construct a CollectionOrderedConstraint - - - - - Modifies the constraint to use an IComparer and returns self. - - - - - Modifies the constraint to use an IComparer<T> and returns self. - - - - - Modifies the constraint to use a Comparison<T> and returns self. - - - - - Modifies the constraint to test ordering by the value of - a specified property and returns self. - - - - - Test whether the collection is ordered - - - - - - - Write a description of the constraint to a MessageWriter - - - - - - Returns the string representation of the constraint. - - - - - - If used performs a reverse comparison - - - - - CollectionSubsetConstraint is used to determine whether - one collection is a subset of another - - - - - Construct a CollectionSubsetConstraint - - The collection that the actual value is expected to be a subset of - - - - Test whether the actual collection is a subset of - the expected collection provided. - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - CollectionTally counts (tallies) the number of - occurences of each object in one or more enumerations. - - - - - Construct a CollectionTally object from a comparer and a collection - - - - - Try to remove an object from the tally - - The object to remove - True if successful, false if the object was not found - - - - Try to remove a set of objects from the tally - - The objects to remove - True if successful, false if any object was not found - - - - The number of objects remaining in the tally - - - - - ComparisonAdapter class centralizes all comparisons of - values in NUnit, adapting to the use of any provided - IComparer, IComparer<T> or Comparison<T> - - - - - Returns a ComparisonAdapter that wraps an IComparer - - - - - Returns a ComparisonAdapter that wraps an IComparer<T> - - - - - Returns a ComparisonAdapter that wraps a Comparison<T> - - - - - Compares two objects - - - - - Gets the default ComparisonAdapter, which wraps an - NUnitComparer object. - - - - - Construct a ComparisonAdapter for an IComparer - - - - - Compares two objects - - - - - - - - Construct a default ComparisonAdapter - - - - - ComparisonAdapter<T> extends ComparisonAdapter and - allows use of an IComparer<T> or Comparison<T> - to actually perform the comparison. - - - - - Construct a ComparisonAdapter for an IComparer<T> - - - - - Compare a Type T to an object - - - - - Construct a ComparisonAdapter for a Comparison<T> - - - - - Compare a Type T to an object - - - - - Abstract base class for constraints that compare values to - determine if one is greater than, equal to or less than - the other. This class supplies the Using modifiers. - - - - - ComparisonAdapter to be used in making the comparison - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - - - Modifies the constraint to use an IComparer and returns self - - - - - Modifies the constraint to use an IComparer<T> and returns self - - - - - Modifies the constraint to use a Comparison<T> and returns self - - - - - Delegate used to delay evaluation of the actual value - to be used in evaluating a constraint - - - - - ConstraintBuilder maintains the stacks that are used in - processing a ConstraintExpression. An OperatorStack - is used to hold operators that are waiting for their - operands to be reognized. a ConstraintStack holds - input constraints as well as the results of each - operator applied. - - - - - Initializes a new instance of the class. - - - - - Appends the specified operator to the expression by first - reducing the operator stack and then pushing the new - operator on the stack. - - The operator to push. - - - - Appends the specified constraint to the expresson by pushing - it on the constraint stack. - - The constraint to push. - - - - Sets the top operator right context. - - The right context. - - - - Reduces the operator stack until the topmost item - precedence is greater than or equal to the target precedence. - - The target precedence. - - - - Resolves this instance, returning a Constraint. If the builder - is not currently in a resolvable state, an exception is thrown. - - The resolved constraint - - - - Gets a value indicating whether this instance is resolvable. - - - true if this instance is resolvable; otherwise, false. - - - - - OperatorStack is a type-safe stack for holding ConstraintOperators - - - - - Initializes a new instance of the class. - - The builder. - - - - Pushes the specified operator onto the stack. - - The op. - - - - Pops the topmost operator from the stack. - - - - - - Gets a value indicating whether this is empty. - - true if empty; otherwise, false. - - - - Gets the topmost operator without modifying the stack. - - The top. - - - - ConstraintStack is a type-safe stack for holding Constraints - - - - - Initializes a new instance of the class. - - The builder. - - - - Pushes the specified constraint. As a side effect, - the constraint's builder field is set to the - ConstraintBuilder owning this stack. - - The constraint. - - - - Pops this topmost constrait from the stack. - As a side effect, the constraint's builder - field is set to null. - - - - - - Gets a value indicating whether this is empty. - - true if empty; otherwise, false. - - - - Gets the topmost constraint without modifying the stack. - - The topmost constraint - - - - ConstraintExpression represents a compound constraint in the - process of being constructed from a series of syntactic elements. - - Individual elements are appended to the expression as they are - reognized. Once an actual Constraint is appended, the expression - returns a resolvable Constraint. - - - - - ConstraintExpressionBase is the abstract base class for the - ConstraintExpression class, which represents a - compound constraint in the process of being constructed - from a series of syntactic elements. - - NOTE: ConstraintExpressionBase is separate because the - ConstraintExpression class was generated in earlier - versions of NUnit. The two classes may be combined - in a future version. - - - - - The ConstraintBuilder holding the elements recognized so far - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the - class passing in a ConstraintBuilder, which may be pre-populated. - - The builder. - - - - Returns a string representation of the expression as it - currently stands. This should only be used for testing, - since it has the side-effect of resolving the expression. - - - - - - Appends an operator to the expression and returns the - resulting expression itself. - - - - - Appends a self-resolving operator to the expression and - returns a new ResolvableConstraintExpression. - - - - - Appends a constraint to the expression and returns that - constraint, which is associated with the current state - of the expression being built. - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the - class passing in a ConstraintBuilder, which may be pre-populated. - - The builder. - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding only if a specified number of them succeed. - - - - - Returns a new PropertyConstraintExpression, which will either - test for the existence of the named property on the object - being tested or apply any following constraint to that property. - - - - - Returns a new AttributeConstraint checking for the - presence of a particular attribute on an object. - - - - - Returns a new AttributeConstraint checking for the - presence of a particular attribute on an object. - - - - - Returns the constraint provided as an argument - used to allow custom - custom constraints to easily participate in the syntax. - - - - - Returns the constraint provided as an argument - used to allow custom - custom constraints to easily participate in the syntax. - - - - - Returns a constraint that tests two items for equality - - - - - Returns a constraint that tests that two references are the same object - - - - - Returns a constraint that tests whether the - actual value is greater than the suppled argument - - - - - Returns a constraint that tests whether the - actual value is greater than or equal to the suppled argument - - - - - Returns a constraint that tests whether the - actual value is greater than or equal to the suppled argument - - - - - Returns a constraint that tests whether the - actual value is less than the suppled argument - - - - - Returns a constraint that tests whether the - actual value is less than or equal to the suppled argument - - - - - Returns a constraint that tests whether the - actual value is less than or equal to the suppled argument - - - - - Returns a constraint that tests whether the actual - value is of the exact type supplied as an argument. - - - - - Returns a constraint that tests whether the actual - value is of the exact type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is a collection containing the same elements as the - collection supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is a subset of the collection supplied as an argument. - - - - - Returns a new CollectionContainsConstraint checking for the - presence of a particular object in the collection. - - - - - Returns a new CollectionContainsConstraint checking for the - presence of a particular object in the collection. - - - - - Returns a new ContainsConstraint. This constraint - will, in turn, make use of the appropriate second-level - constraint, depending on the type of the actual argument. - This overload is only used if the item sought is a string, - since any other type implies that we are looking for a - collection member. - - - - - Returns a constraint that succeeds if the actual - value contains the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value contains the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value starts with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value starts with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value ends with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value ends with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value matches the regular expression supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value matches the regular expression supplied as an argument. - - - - - Returns a constraint that tests whether the path provided - is the same as an expected path after canonicalization. - - - - - Returns a constraint that tests whether the path provided - is the same path or under an expected path after canonicalization. - - - - - Returns a constraint that tests whether the path provided - is the same path or under an expected path after canonicalization. - - - - - Returns a constraint that tests whether the actual value falls - within a specified range. - - - - - Returns a ConstraintExpression that negates any - following constraint. - - - - - Returns a ConstraintExpression that negates any - following constraint. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if all of them succeed. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if at least one of them succeeds. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if all of them fail. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the Length property of the object being tested. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the Count property of the object being tested. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the Message property of the object being tested. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the InnerException property of the object being tested. - - - - - With is currently a NOP - reserved for future use. - - - - - Returns a constraint that tests for null - - - - - Returns a constraint that tests for True - - - - - Returns a constraint that tests for False - - - - - Returns a constraint that tests for a positive value - - - - - Returns a constraint that tests for a negative value - - - - - Returns a constraint that tests for NaN - - - - - Returns a constraint that tests for empty - - - - - Returns a constraint that tests whether a collection - contains all unique items. - - - - - Returns a constraint that tests whether an object graph is serializable in binary format. - - - - - Returns a constraint that tests whether an object graph is serializable in xml format. - - - - - Returns a constraint that tests whether a collection is ordered - - - - - ContainsConstraint tests a whether a string contains a substring - or a collection contains an object. It postpones the decision of - which test to use until the type of the actual argument is known. - This allows testing whether a string is contained in a collection - or as a substring of another string using the same syntax. - - - - - Initializes a new instance of the class. - - The expected. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Flag the constraint to use the supplied IComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied Comparison object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IEqualityComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IEqualityComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to ignore case and return self. - - - - - Applies a delay to the match so that a match can be evaluated in the future. - - - - - Creates a new DelayedConstraint - - The inner constraint two decorate - The time interval after which the match is performed - If the value of is less than 0 - - - - Creates a new DelayedConstraint - - The inner constraint two decorate - The time interval after which the match is performed - The time interval used for polling - If the value of is less than 0 - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for if the base constraint fails, false if it succeeds - - - - Test whether the constraint is satisfied by a delegate - - The delegate whose value is to be tested - True for if the base constraint fails, false if it succeeds - - - - Test whether the constraint is satisfied by a given reference. - Overridden to wait for the specified delay period before - calling the base constraint with the dereferenced value. - - A reference to the value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a MessageWriter. - - The writer on which the actual value is displayed - - - - Returns the string representation of the constraint. - - - - - EmptyCollectionConstraint tests whether a collection is empty. - - - - - Check that the collection is empty - - - - - - - Write the constraint description to a MessageWriter - - - - - - EmptyConstraint tests a whether a string or collection is empty, - postponing the decision about which test is applied until the - type of the actual argument is known. - - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - EmptyDirectoryConstraint is used to test that a directory is empty - - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a - MessageWriter. The default implementation simply writes - the raw value of actual, leaving it to the writer to - perform any formatting. - - The writer on which the actual value is displayed - - - - EmptyStringConstraint tests whether a string is empty. - - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - EndsWithConstraint can test whether a string ends - with an expected substring. - - - - - StringConstraint is the abstract base for constraints - that operate on strings. It supports the IgnoreCase - modifier for string operations. - - - - - The expected value - - - - - Indicates whether tests should be case-insensitive - - - - - Constructs a StringConstraint given an expected value - - The expected value - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Test whether the constraint is satisfied by a given string - - The string to be tested - True for success, false for failure - - - - Modify the constraint to ignore case in matching. - - - - - Initializes a new instance of the class. - - The expected string - - - - Test whether the constraint is matched by the actual value. - This is a template method, which calls the IsMatch method - of the derived class. - - - - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - EqualConstraint is able to compare an actual value with the - expected value provided in its constructor. Two objects are - considered equal if both are null, or if both have the same - value. NUnit has special semantics for some object types. - - - - - If true, strings in error messages will be clipped - - - - - NUnitEqualityComparer used to test equality. - - - - - Initializes a new instance of the class. - - The expected value. - - - - Flag the constraint to use a tolerance when determining equality. - - Tolerance value to be used - Self. - - - - Flag the constraint to use the supplied IComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied Comparison object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IEqualityComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IEqualityComparer object. - - The IComparer object to use. - Self. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write a failure message. Overridden to provide custom - failure messages for EqualConstraint. - - The MessageWriter to write to - - - - Write description of this constraint - - The MessageWriter to write to - - - - Display the failure information for two collections that did not match. - - The MessageWriter on which to display - The expected collection. - The actual collection - The depth of this failure in a set of nested collections - - - - Displays a single line showing the types and sizes of the expected - and actual enumerations, collections or arrays. If both are identical, - the value is only shown once. - - The MessageWriter on which to display - The expected collection or array - The actual collection or array - The indentation level for the message line - - - - Displays a single line showing the point in the expected and actual - arrays at which the comparison failed. If the arrays have different - structures or dimensions, both values are shown. - - The MessageWriter on which to display - The expected array - The actual array - Index of the failure point in the underlying collections - The indentation level for the message line - - - - Display the failure information for two IEnumerables that did not match. - - The MessageWriter on which to display - The expected enumeration. - The actual enumeration - The depth of this failure in a set of nested collections - - - - Flag the constraint to ignore case and return self. - - - - - Flag the constraint to suppress string clipping - and return self. - - - - - Flag the constraint to compare arrays as collections - and return self. - - - - - Switches the .Within() modifier to interpret its tolerance as - a distance in representable values (see remarks). - - Self. - - Ulp stands for "unit in the last place" and describes the minimum - amount a given value can change. For any integers, an ulp is 1 whole - digit. For floating point values, the accuracy of which is better - for smaller numbers and worse for larger numbers, an ulp depends - on the size of the number. Using ulps for comparison of floating - point results instead of fixed tolerances is safer because it will - automatically compensate for the added inaccuracy of larger numbers. - - - - - Switches the .Within() modifier to interpret its tolerance as - a percentage that the actual values is allowed to deviate from - the expected value. - - Self - - - - Causes the tolerance to be interpreted as a TimeSpan in days. - - Self - - - - Causes the tolerance to be interpreted as a TimeSpan in hours. - - Self - - - - Causes the tolerance to be interpreted as a TimeSpan in minutes. - - Self - - - - Causes the tolerance to be interpreted as a TimeSpan in seconds. - - Self - - - - Causes the tolerance to be interpreted as a TimeSpan in milliseconds. - - Self - - - - Causes the tolerance to be interpreted as a TimeSpan in clock ticks. - - Self - - - - EqualityAdapter class handles all equality comparisons - that use an IEqualityComparer, IEqualityComparer<T> - or a ComparisonAdapter. - - - - - Compares two objects, returning true if they are equal - - - - - Returns true if the two objects can be compared by this adapter. - The base adapter cannot handle IEnumerables except for strings. - - - - - Returns an EqualityAdapter that wraps an IComparer. - - - - - Returns an EqualityAdapter that wraps an IEqualityComparer. - - - - - Returns an EqualityAdapter that wraps an IEqualityComparer<T>. - - - - - Returns an EqualityAdapter that wraps an IComparer<T>. - - - - - Returns an EqualityAdapter that wraps a Comparison<T>. - - - - - EqualityAdapter that wraps an IComparer. - - - - - Returns true if the two objects can be compared by this adapter. - Generic adapter requires objects of the specified type. - - - - - EqualityAdapter that wraps an IComparer. - - - - - EqualityAdapterList represents a list of EqualityAdapters - in a common class across platforms. - - - - - ExactCountConstraint applies another constraint to each - item in a collection, succeeding only if a specified - number of items succeed. - - - - - Construct an ExactCountConstraint on top of an existing constraint - - - - - - - Apply the item constraint to each item in the collection, - succeeding only if the expected number of items pass. - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - ExactTypeConstraint is used to test that an object - is of the exact type provided in the constructor - - - - - Construct an ExactTypeConstraint for a given Type - - The expected Type. - - - - Test that an object is of the exact type specified - - The actual value. - True if the tested object is of the exact type provided, otherwise false. - - - - Write the description of this constraint to a MessageWriter - - The MessageWriter to use - - - - ExceptionTypeConstraint is a special version of ExactTypeConstraint - used to provided detailed info about the exception thrown in - an error message. - - - - - Constructs an ExceptionTypeConstraint - - - - - Write the actual value for a failing constraint test to a - MessageWriter. Overriden to write additional information - in the case of an Exception. - - The MessageWriter to use - - - - FailurePoint class represents one point of failure - in an equality test. - - - - - The location of the failure - - - - - The expected value - - - - - The actual value - - - - - Indicates whether the expected value is valid - - - - - Indicates whether the actual value is valid - - - - - FailurePointList represents a set of FailurePoints - in a cross-platform way. - - - - - FalseConstraint tests that the actual value is false - - - - - Initializes a new instance of the class. - - - - Helper routines for working with floating point numbers - - - The floating point comparison code is based on this excellent article: - http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm - - - "ULP" means Unit in the Last Place and in the context of this library refers to - the distance between two adjacent floating point numbers. IEEE floating point - numbers can only represent a finite subset of natural numbers, with greater - accuracy for smaller numbers and lower accuracy for very large numbers. - - - If a comparison is allowed "2 ulps" of deviation, that means the values are - allowed to deviate by up to 2 adjacent floating point values, which might be - as low as 0.0000001 for small numbers or as high as 10.0 for large numbers. - - - - - Compares two floating point values for equality - First floating point value to be compared - Second floating point value t be compared - - Maximum number of representable floating point values that are allowed to - be between the left and the right floating point values - - True if both numbers are equal or close to being equal - - - Floating point values can only represent a finite subset of natural numbers. - For example, the values 2.00000000 and 2.00000024 can be stored in a float, - but nothing inbetween them. - - - This comparison will count how many possible floating point values are between - the left and the right number. If the number of possible values between both - numbers is less than or equal to maxUlps, then the numbers are considered as - being equal. - - - Implementation partially follows the code outlined here: - http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ - - - - - Compares two double precision floating point values for equality - First double precision floating point value to be compared - Second double precision floating point value t be compared - - Maximum number of representable double precision floating point values that are - allowed to be between the left and the right double precision floating point values - - True if both numbers are equal or close to being equal - - - Double precision floating point values can only represent a limited series of - natural numbers. For example, the values 2.0000000000000000 and 2.0000000000000004 - can be stored in a double, but nothing inbetween them. - - - This comparison will count how many possible double precision floating point - values are between the left and the right number. If the number of possible - values between both numbers is less than or equal to maxUlps, then the numbers - are considered as being equal. - - - Implementation partially follows the code outlined here: - http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ - - - - - - Reinterprets the memory contents of a floating point value as an integer value - - - Floating point value whose memory contents to reinterpret - - - The memory contents of the floating point value interpreted as an integer - - - - - Reinterprets the memory contents of a double precision floating point - value as an integer value - - - Double precision floating point value whose memory contents to reinterpret - - - The memory contents of the double precision floating point value - interpreted as an integer - - - - - Reinterprets the memory contents of an integer as a floating point value - - Integer value whose memory contents to reinterpret - - The memory contents of the integer value interpreted as a floating point value - - - - - Reinterprets the memory contents of an integer value as a double precision - floating point value - - Integer whose memory contents to reinterpret - - The memory contents of the integer interpreted as a double precision - floating point value - - - - Union of a floating point variable and an integer - - - The union's value as a floating point variable - - - The union's value as an integer - - - The union's value as an unsigned integer - - - Union of a double precision floating point variable and a long - - - The union's value as a double precision floating point variable - - - The union's value as a long - - - The union's value as an unsigned long - - - - Tests whether a value is greater than the value supplied to its constructor - - - - - The value against which a comparison is to be made - - - - - Initializes a new instance of the class. - - The expected value. - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Tests whether a value is greater than or equal to the value supplied to its constructor - - - - - The value against which a comparison is to be made - - - - - Initializes a new instance of the class. - - The expected value. - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - InstanceOfTypeConstraint is used to test that an object - is of the same type provided or derived from it. - - - - - Construct an InstanceOfTypeConstraint for the type provided - - The expected Type - - - - Test whether an object is of the specified type or a derived type - - The object to be tested - True if the object is of the provided type or derives from it, otherwise false. - - - - Write a description of this constraint to a MessageWriter - - The MessageWriter to use - - - - Tests whether a value is less than the value supplied to its constructor - - - - - The value against which a comparison is to be made - - - - - Initializes a new instance of the class. - - The expected value. - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Tests whether a value is less than or equal to the value supplied to its constructor - - - - - The value against which a comparison is to be made - - - - - Initializes a new instance of the class. - - The expected value. - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Static methods used in creating messages - - - - - Static string used when strings are clipped - - - - - Returns the representation of a type as used in NUnitLite. - This is the same as Type.ToString() except for arrays, - which are displayed with their declared sizes. - - - - - - - Converts any control characters in a string - to their escaped representation. - - The string to be converted - The converted string - - - - Return the a string representation for a set of indices into an array - - Array of indices for which a string is needed - - - - Get an array of indices representing the point in a enumerable, - collection or array corresponding to a single int index into the - collection. - - The collection to which the indices apply - Index in the collection - Array of indices - - - - Clip a string to a given length, starting at a particular offset, returning the clipped - string with ellipses representing the removed parts - - The string to be clipped - The maximum permitted length of the result string - The point at which to start clipping - The clipped string - - - - Clip the expected and actual strings in a coordinated fashion, - so that they may be displayed together. - - - - - - - - - Shows the position two strings start to differ. Comparison - starts at the start index. - - The expected string - The actual string - The index in the strings at which comparison should start - Boolean indicating whether case should be ignored - -1 if no mismatch found, or the index where mismatch found - - - - NaNConstraint tests that the actual value is a double or float NaN - - - - - Test that the actual value is an NaN - - - - - - - Write the constraint description to a specified writer - - - - - - NoItemConstraint applies another constraint to each - item in a collection, failing if any of them succeeds. - - - - - Construct a NoItemConstraint on top of an existing constraint - - - - - - Apply the item constraint to each item in the collection, - failing if any item fails. - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - NotConstraint negates the effect of some other constraint - - - - - Initializes a new instance of the class. - - The base constraint to be negated. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for if the base constraint fails, false if it succeeds - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a MessageWriter. - - The writer on which the actual value is displayed - - - - NullConstraint tests that the actual value is null - - - - - Initializes a new instance of the class. - - - - - NullEmptyStringConstraint tests whether a string is either null or empty. - - - - - Constructs a new NullOrEmptyStringConstraint - - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - The Numerics class contains common operations on numeric values. - - - - - Checks the type of the object, returning true if - the object is a numeric type. - - The object to check - true if the object is a numeric type - - - - Checks the type of the object, returning true if - the object is a floating point numeric type. - - The object to check - true if the object is a floating point numeric type - - - - Checks the type of the object, returning true if - the object is a fixed point numeric type. - - The object to check - true if the object is a fixed point numeric type - - - - Test two numeric values for equality, performing the usual numeric - conversions and using a provided or default tolerance. If the tolerance - provided is Empty, this method may set it to a default tolerance. - - The expected value - The actual value - A reference to the tolerance in effect - True if the values are equal - - - - Compare two numeric values, performing the usual numeric conversions. - - The expected value - The actual value - The relationship of the values to each other - - - - NUnitComparer encapsulates NUnit's default behavior - in comparing two objects. - - - - - Compares two objects - - - - - - - - Returns the default NUnitComparer. - - - - - Generic version of NUnitComparer - - - - - - Compare two objects of the same type - - - - - NUnitEqualityComparer encapsulates NUnit's handling of - equality tests between objects. - - - - - - - - - - Compares two objects for equality within a tolerance - - The first object to compare - The second object to compare - The tolerance to use in the comparison - - - - - If true, all string comparisons will ignore case - - - - - If true, arrays will be treated as collections, allowing - those of different dimensions to be compared - - - - - Comparison objects used in comparisons for some constraints. - - - - - List of points at which a failure occured. - - - - - RecursionDetector used to check for recursion when - evaluating self-referencing enumerables. - - - - - Compares two objects for equality within a tolerance, setting - the tolerance to the actual tolerance used if an empty - tolerance is supplied. - - - - - Helper method to compare two arrays - - - - - Method to compare two DirectoryInfo objects - - first directory to compare - second directory to compare - true if equivalent, false if not - - - - Returns the default NUnitEqualityComparer - - - - - Gets and sets a flag indicating whether case should - be ignored in determining equality. - - - - - Gets and sets a flag indicating that arrays should be - compared as collections, without regard to their shape. - - - - - Gets the list of external comparers to be used to - test for equality. They are applied to members of - collections, in place of NUnit's own logic. - - - - - Gets the list of failure points for the last Match performed. - The list consists of objects to be interpreted by the caller. - This generally means that the caller may only make use of - objects it has placed on the list at a particular depthy. - - - - - RecursionDetector detects when a comparison - between two enumerables has reached a point - where the same objects that were previously - compared are again being compared. This allows - the caller to stop the comparison if desired. - - - - - Check whether two objects have previously - been compared, returning true if they have. - The two objects are remembered, so that a - second call will always return true. - - - - - OrConstraint succeeds if either member succeeds - - - - - Create an OrConstraint from two other constraints - - The first constraint - The second constraint - - - - Apply the member constraints to an actual value, succeeding - succeeding as soon as one of them succeeds. - - The actual value - True if either constraint succeeded - - - - Write a description for this contraint to a MessageWriter - - The MessageWriter to receive the description - - - - PathConstraint serves as the abstract base of constraints - that operate on paths and provides several helper methods. - - - - - The expected path used in the constraint - - - - - Flag indicating whether a caseInsensitive comparison should be made - - - - - Construct a PathConstraint for a give expected path - - The expected path - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Returns true if the expected path and actual path match - - - - - Returns the string representation of this constraint - - - - - Transform the provided path to its canonical form so that it - may be more easily be compared with other paths. - - The original path - The path in canonical form - - - - Test whether one path in canonical form is under another. - - The first path - supposed to be the parent path - The second path - supposed to be the child path - Indicates whether case should be ignored - - - - - Modifies the current instance to be case-insensitve - and returns it. - - - - - Modifies the current instance to be case-sensitve - and returns it. - - - - - Predicate constraint wraps a Predicate in a constraint, - returning success if the predicate is true. - - - - - Construct a PredicateConstraint from a predicate - - - - - Determines whether the predicate succeeds when applied - to the actual value. - - - - - Writes the description to a MessageWriter - - - - - PropertyConstraint extracts a named property and uses - its value as the actual value for a chained constraint. - - - - - Initializes a new instance of the class. - - The name. - The constraint to apply to the property. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a - MessageWriter. The default implementation simply writes - the raw value of actual, leaving it to the writer to - perform any formatting. - - The writer on which the actual value is displayed - - - - Returns the string representation of the constraint. - - - - - - PropertyExistsConstraint tests that a named property - exists on the object provided through Match. - - Originally, PropertyConstraint provided this feature - in addition to making optional tests on the vaue - of the property. The two constraints are now separate. - - - - - Initializes a new instance of the class. - - The name of the property. - - - - Test whether the property exists for a given object - - The object to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a - MessageWriter. - - The writer on which the actual value is displayed - - - - Returns the string representation of the constraint. - - - - - - RangeConstraint tests whether two values are within a - specified range. - - - - - Initializes a new instance of the class. - - From. - To. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - RegexConstraint can test whether a string matches - the pattern provided. - - - - - Initializes a new instance of the class. - - The pattern. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - ResolvableConstraintExpression is used to represent a compound - constraint being constructed at a point where the last operator - may either terminate the expression or may have additional - qualifying constraints added to it. - - It is used, for example, for a Property element or for - an Exception element, either of which may be optionally - followed by constraints that apply to the property or - exception. - - - - - Create a new instance of ResolvableConstraintExpression - - - - - Create a new instance of ResolvableConstraintExpression, - passing in a pre-populated ConstraintBuilder. - - - - - Resolve the current expression to a Constraint - - - - - This operator creates a constraint that is satisfied only if both - argument constraints are satisfied. - - - - - This operator creates a constraint that is satisfied only if both - argument constraints are satisfied. - - - - - This operator creates a constraint that is satisfied only if both - argument constraints are satisfied. - - - - - This operator creates a constraint that is satisfied if either - of the argument constraints is satisfied. - - - - - This operator creates a constraint that is satisfied if either - of the argument constraints is satisfied. - - - - - This operator creates a constraint that is satisfied if either - of the argument constraints is satisfied. - - - - - This operator creates a constraint that is satisfied if the - argument constraint is not satisfied. - - - - - Appends an And Operator to the expression - - - - - Appends an Or operator to the expression. - - - - - ReusableConstraint wraps a constraint expression after - resolving it so that it can be reused consistently. - - - - - Construct a ReusableConstraint from a constraint expression - - The expression to be resolved and reused - - - - Converts a constraint to a ReusableConstraint - - The constraint to be converted - A ReusableConstraint - - - - Returns the string representation of the constraint. - - A string representing the constraint - - - - Resolves the ReusableConstraint by returning the constraint - that it originally wrapped. - - A resolved constraint - - - - SameAsConstraint tests whether an object is identical to - the object passed to its constructor - - - - - Initializes a new instance of the class. - - The expected object. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Summary description for SamePathConstraint. - - - - - Initializes a new instance of the class. - - The expected path - - - - Test whether the constraint is satisfied by a given value - - The expected path - The actual path - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - SamePathOrUnderConstraint tests that one path is under another - - - - - Initializes a new instance of the class. - - The expected path - - - - Test whether the constraint is satisfied by a given value - - The expected path - The actual path - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - SomeItemsConstraint applies another constraint to each - item in a collection, succeeding if any of them succeeds. - - - - - Construct a SomeItemsConstraint on top of an existing constraint - - - - - - Apply the item constraint to each item in the collection, - succeeding if any item succeeds. - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - StartsWithConstraint can test whether a string starts - with an expected substring. - - - - - Initializes a new instance of the class. - - The expected string - - - - Test whether the constraint is matched by the actual value. - This is a template method, which calls the IsMatch method - of the derived class. - - - - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - SubPathConstraint tests that the actual path is under the expected path - - - - - Initializes a new instance of the class. - - The expected path - - - - Test whether the constraint is satisfied by a given value - - The expected path - The actual path - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - SubstringConstraint can test whether a string contains - the expected substring. - - - - - Initializes a new instance of the class. - - The expected. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - ThrowsConstraint is used to test the exception thrown by - a delegate by applying a constraint to it. - - - - - Initializes a new instance of the class, - using a constraint to be applied to the exception. - - A constraint to apply to the caught exception. - - - - Executes the code of the delegate and captures any exception. - If a non-null base constraint was provided, it applies that - constraint to the exception. - - A delegate representing the code to be tested - True if an exception is thrown and the constraint succeeds, otherwise false - - - - Converts an ActualValueDelegate to a TestDelegate - before calling the primary overload. - - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a - MessageWriter. The default implementation simply writes - the raw value of actual, leaving it to the writer to - perform any formatting. - - The writer on which the actual value is displayed - - - - Returns the string representation of this constraint - - - - - Get the actual exception thrown - used by Assert.Throws. - - - - - ThrowsNothingConstraint tests that a delegate does not - throw an exception. - - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True if no exception is thrown, otherwise false - - - - Test whether the constraint is satisfied by a given delegate - - Delegate returning the value to be tested - True if no exception is thrown, otherwise false - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a - MessageWriter. Overridden in ThrowsNothingConstraint to write - information about the exception that was actually caught. - - The writer on which the actual value is displayed - - - - The Tolerance class generalizes the notion of a tolerance - within which an equality test succeeds. Normally, it is - used with numeric types, but it can be used with any - type that supports taking a difference between two - objects and comparing that difference to a value. - - - - - Constructs a linear tolerance of a specdified amount - - - - - Constructs a tolerance given an amount and ToleranceMode - - - - - Tests that the current Tolerance is linear with a - numeric value, throwing an exception if it is not. - - - - - Returns an empty Tolerance object, equivalent to - specifying no tolerance. In most cases, it results - in an exact match but for floats and doubles a - default tolerance may be used. - - - - - Returns a zero Tolerance object, equivalent to - specifying an exact match. - - - - - Gets the ToleranceMode for the current Tolerance - - - - - Gets the value of the current Tolerance instance. - - - - - Returns a new tolerance, using the current amount as a percentage. - - - - - Returns a new tolerance, using the current amount in Ulps. - - - - - Returns a new tolerance with a TimeSpan as the amount, using - the current amount as a number of days. - - - - - Returns a new tolerance with a TimeSpan as the amount, using - the current amount as a number of hours. - - - - - Returns a new tolerance with a TimeSpan as the amount, using - the current amount as a number of minutes. - - - - - Returns a new tolerance with a TimeSpan as the amount, using - the current amount as a number of seconds. - - - - - Returns a new tolerance with a TimeSpan as the amount, using - the current amount as a number of milliseconds. - - - - - Returns a new tolerance with a TimeSpan as the amount, using - the current amount as a number of clock ticks. - - - - - Returns true if the current tolerance is empty. - - - - - Modes in which the tolerance value for a comparison can be interpreted. - - - - - The tolerance was created with a value, without specifying - how the value would be used. This is used to prevent setting - the mode more than once and is generally changed to Linear - upon execution of the test. - - - - - The tolerance is used as a numeric range within which - two compared values are considered to be equal. - - - - - Interprets the tolerance as the percentage by which - the two compared values my deviate from each other. - - - - - Compares two values based in their distance in - representable numbers. - - - - - TrueConstraint tests that the actual value is true - - - - - Initializes a new instance of the class. - - - - - UniqueItemsConstraint tests whether all the items in a - collection are unique. - - - - - Check that all items are unique. - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - XmlSerializableConstraint tests whether - an object is serializable in XML format. - - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a - MessageWriter. The default implementation simply writes - the raw value of actual, leaving it to the writer to - perform any formatting. - - The writer on which the actual value is displayed - - - - Returns the string representation of this constraint - - - - - Represents a constraint that succeeds if all the - members of a collection match a base constraint. - - - - - Abstract base for operators that indicate how to - apply a constraint to items in a collection. - - - - - PrefixOperator takes a single constraint and modifies - it's action in some way. - - - - - The ConstraintOperator class is used internally by a - ConstraintBuilder to represent an operator that - modifies or combines constraints. - - Constraint operators use left and right precedence - values to determine whether the top operator on the - stack should be reduced before pushing a new operator. - - - - - The precedence value used when the operator - is about to be pushed to the stack. - - - - - The precedence value used when the operator - is on the top of the stack. - - - - - Reduce produces a constraint from the operator and - any arguments. It takes the arguments from the constraint - stack and pushes the resulting constraint on it. - - - - - - The syntax element preceding this operator - - - - - The syntax element folowing this operator - - - - - The precedence value used when the operator - is about to be pushed to the stack. - - - - - The precedence value used when the operator - is on the top of the stack. - - - - - Reduce produces a constraint from the operator and - any arguments. It takes the arguments from the constraint - stack and pushes the resulting constraint on it. - - - - - - Returns the constraint created by applying this - prefix to another constraint. - - - - - - - Constructs a CollectionOperator - - - - - Returns a constraint that will apply the argument - to the members of a collection, succeeding if - they all succeed. - - - - - Operator that requires both it's arguments to succeed - - - - - Abstract base class for all binary operators - - - - - Reduce produces a constraint from the operator and - any arguments. It takes the arguments from the constraint - stack and pushes the resulting constraint on it. - - - - - - Abstract method that produces a constraint by applying - the operator to its left and right constraint arguments. - - - - - Gets the left precedence of the operator - - - - - Gets the right precedence of the operator - - - - - Construct an AndOperator - - - - - Apply the operator to produce an AndConstraint - - - - - Operator that tests for the presence of a particular attribute - on a type and optionally applies further tests to the attribute. - - - - - Abstract base class for operators that are able to reduce to a - constraint whether or not another syntactic element follows. - - - - - Construct an AttributeOperator for a particular Type - - The Type of attribute tested - - - - Reduce produces a constraint from the operator and - any arguments. It takes the arguments from the constraint - stack and pushes the resulting constraint on it. - - - - - Represents a constraint that succeeds if the specified - count of members of a collection match a base constraint. - - - - - Construct an ExactCountOperator for a specified count - - The expected count - - - - Returns a constraint that will apply the argument - to the members of a collection, succeeding if - none of them succeed. - - - - - Represents a constraint that succeeds if none of the - members of a collection match a base constraint. - - - - - Returns a constraint that will apply the argument - to the members of a collection, succeeding if - none of them succeed. - - - - - Negates the test of the constraint it wraps. - - - - - Constructs a new NotOperator - - - - - Returns a NotConstraint applied to its argument. - - - - - Operator that requires at least one of it's arguments to succeed - - - - - Construct an OrOperator - - - - - Apply the operator to produce an OrConstraint - - - - - Operator used to test for the presence of a named Property - on an object and optionally apply further tests to the - value of that property. - - - - - Constructs a PropOperator for a particular named property - - - - - Reduce produces a constraint from the operator and - any arguments. It takes the arguments from the constraint - stack and pushes the resulting constraint on it. - - - - - - Gets the name of the property to which the operator applies - - - - - Represents a constraint that succeeds if any of the - members of a collection match a base constraint. - - - - - Returns a constraint that will apply the argument - to the members of a collection, succeeding if - any of them succeed. - - - - - Operator that tests that an exception is thrown and - optionally applies further tests to the exception. - - - - - Construct a ThrowsOperator - - - - - Reduce produces a constraint from the operator and - any arguments. It takes the arguments from the constraint - stack and pushes the resulting constraint on it. - - - - - Represents a constraint that simply wraps the - constraint provided as an argument, without any - further functionality, but which modifes the - order of evaluation because of its precedence. - - - - - Constructor for the WithOperator - - - - - Returns a constraint that wraps its argument - - - - - Thrown when an assertion failed. - - - - The error message that explains - the reason for the exception - - - The error message that explains - the reason for the exception - The exception that caused the - current exception - - - - Serialization Constructor - - - - - Thrown when an assertion failed. - - - - - - - The error message that explains - the reason for the exception - The exception that caused the - current exception - - - - Serialization Constructor - - - - - Thrown when a test executes inconclusively. - - - - The error message that explains - the reason for the exception - - - The error message that explains - the reason for the exception - The exception that caused the - current exception - - - - Serialization Constructor - - - - - Thrown when an assertion failed. - - - - - - - The error message that explains - the reason for the exception - The exception that caused the - current exception - - - - Serialization Constructor - - - - - - - - - - - Compares two objects of a given Type for equality within a tolerance - - The first object to compare - The second object to compare - The tolerance to use in the comparison - - - - diff --git a/HandsetDetectionAPI/obj/Debug/HandsetDetectionAPI.dll b/HandsetDetectionAPI/obj/Debug/HandsetDetectionAPI.dll deleted file mode 100644 index 3c50fa44679cac700f1dfa51ac919d8e3d96696f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 206336 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 diff --git a/HandsetDetectionAPIKit4/Benchmark.aspx b/HandsetDetectionAPIKit4/Benchmark.aspx new file mode 100644 index 00000000..32266b6a --- /dev/null +++ b/HandsetDetectionAPIKit4/Benchmark.aspx @@ -0,0 +1,31 @@ +<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Benchmark.aspx.cs" Inherits="Web.Benchmark" %> + + + + + + Test headers + + + + +
    +
    + +

    + Elapsed Time : + Total Detections : + Detection per second : +

    +
    +
    + + \ No newline at end of file diff --git a/HandsetDetectionAPIKit4/Benchmark.aspx.cs b/HandsetDetectionAPIKit4/Benchmark.aspx.cs new file mode 100644 index 00000000..fbb2d180 --- /dev/null +++ b/HandsetDetectionAPIKit4/Benchmark.aspx.cs @@ -0,0 +1,101 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Web.UI; +using HandsetDetectionAPI; + +namespace Web +{ + public partial class Benchmark : Page + { + private List> _headers = new List>(); + public string ConfigFile = "//hdUltimateConfig.json"; + public string DataFile = "benchmarkData.txt"; + public long TotalMilliSec { get; set; } + public DateTime EndTime { get; set; } + public int TotalCount { get; set; } + + protected void Page_Load(dynamic sender, EventArgs e) + { + var fileName = "/benchmarkData.txt"; + try + { + if (File.Exists(Server.MapPath(fileName))) + { + using (var sr = new StreamReader(Server.MapPath(fileName))) + { + string line; + + while ((line = sr.ReadLine()) != null) + { + var item = line.Trim().Split(new[] { "|" }, StringSplitOptions.None); + var requestBody = new Dictionary(); + requestBody["user-agent"] = item[0]; + if (item.Length > 1) + { + requestBody["x-wap-profile"] = item[1]; + } + else + { + requestBody["x-wap-profile"] = string.Empty; + } + _headers.Add(requestBody); + + } + } + } + else + { + Response.Write("File not exist."); + } + } + catch (Exception ex) + { + Response.Write("File error: " + ex.Message); + } + var objHd = new HD4(Request); + + FlyThrough(objHd); + lblTotDetect.Text = TotalCount.ToString(); + lblTimeElapsed.Text = (TotalMilliSec / 1000).ToString(CultureInfo.InvariantCulture) + " sec."; + lblDetectPerSec.Text = ((Convert.ToDouble(TotalCount) * 1000) / TotalMilliSec).ToString(CultureInfo.InvariantCulture); + } + + public void FlyThrough(HD4 objHd) + { + var deviceModelList = new List(); + TotalCount = 1; + Stopwatch stopwatch = new Stopwatch(); + stopwatch.Reset(); + stopwatch.Start(); + foreach (var header in _headers) + { + var result = objHd.deviceDetect(header); + TotalCount++; + + } + + stopwatch.Stop(); + TotalMilliSec = stopwatch.ElapsedMilliseconds; + + grdDeviceModel.DataSource = deviceModelList; + grdDeviceModel.DataBind(); + + } + } + + + public class DeviceModel + { + public string Count { get; set; } + public string Vendor { get; set; } + public string Model { get; set; } + public string Platform { get; set; } + public string PlatformVersion { get; set; } + public string Browser { get; set; } + public string BrowserVersion { get; set; } + public string HttpHeaders { get; set; } + } +} \ No newline at end of file diff --git a/HandsetDetectionAPIKit4/Benchmark.aspx.designer.cs b/HandsetDetectionAPIKit4/Benchmark.aspx.designer.cs new file mode 100644 index 00000000..d7b4843b --- /dev/null +++ b/HandsetDetectionAPIKit4/Benchmark.aspx.designer.cs @@ -0,0 +1,60 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Web { + + + public partial class Benchmark { + + /// + /// form1 control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.HtmlControls.HtmlForm form1; + + /// + /// grdDeviceModel control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.GridView grdDeviceModel; + + /// + /// lblTimeElapsed control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblTimeElapsed; + + /// + /// lblTotDetect control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblTotDetect; + + /// + /// lblDetectPerSec control. + /// + /// + /// Auto-generated field. + /// To modify move field declaration from designer file to code-behind file. + /// + protected global::System.Web.UI.WebControls.Label lblDetectPerSec; + } +} diff --git a/HandsetDetectionAPIKit4/Web.csproj b/HandsetDetectionAPIKit4/Web.csproj index c091fb9f..0529914e 100644 --- a/HandsetDetectionAPIKit4/Web.csproj +++ b/HandsetDetectionAPIKit4/Web.csproj @@ -57,6 +57,8 @@ + + @@ -77,6 +79,13 @@ + + Benchmark.aspx + ASPXCodeBehind + + + Benchmark.aspx + Default.aspx ASPXCodeBehind diff --git a/HandsetDetectionAPIKit4/benchmarkData.txt b/HandsetDetectionAPIKit4/benchmarkData.txt new file mode 100644 index 00000000..d47d3307 --- /dev/null +++ b/HandsetDetectionAPIKit4/benchmarkData.txt @@ -0,0 +1,1066 @@ +Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36| +Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; GTB7.1; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; InfoPath.2; .NET CLR 3.5.30729; .NET4.0C; .NET CLR 3.0.30729; AskTbFWV5/5.12.2.16749; 978803803)| +WordPress/3.1; http://www.rimplaybook.biz| +Opera/9.80 (X11; Linux zvav; U; en) Presto/2.8.119 Version/10.54| +Opera/9.80 (X11; Linux zvav; U; es) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.22) Gecko/20110902 Firefox/3.6.22 ( .NET CLR 3.5.30729) Swapper 1.0.4| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; Swapper 1.0.5; Orange 7.4; Orange 8.0; SIMBAR={77B58263-85B3-4334-AB81-ECEEB41FE0EA}; NaviWoo2.0; InfoPath.2; .NET CLR 1.1.4322; Swapper 1.0.5; .NET CLR 2.0.50727; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; .NET CLR 3.0.04506.30)| +Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; BOLT/2.702) AppleWebKit/534.6 (KHTML, like Gecko) Version/5.0 Safari/534.6.3| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; GTB6.6; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; SLCC1; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; 998603905703; Build/13.00319; 66660811703; 669607972803; 88980603; 668604633903; 9689028603; 66760656903; 896707603; 89670703903; 87890045703; 976905703; 988707903; 699902803803; 79680703; 999603803; 799801903; 97780703; 9789006903; 889800703; 877903667903; 787904628603; 97790972903; 7978010803; 666606| +WordPress/MU; http://hetblackberrynieuws.wordpress.com| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64; FunWebProducts; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30618; FunWebProducts; 797803803; layout/4.02124)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; Swapper 1.0.4; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; MDDR; Swapper 1.0.4; .NET4.0C)| +Opera/9.80 (X11; Linux i686; U; vi) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; BOLT/2.701) AppleWebKit/534.6 (KHTML, like Gecko) Version/5.0 Safari/534.6.3| +Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; 979803803; Library2.02045)| +Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; BOLT/2.700) AppleWebKit/534.6 (KHTML, like Gecko) Version/5.0 Safari/534.6.3| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SIMBAR={F5F6C5D0-6CF5-11DC-A19D-0013A950183F}; GTB7.1; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; MSN Optimized;DE; Swapper 1.0.5; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; MSN Optimized;DE)| +Opera/9.80 (X11; Linux i686; U; en) Presto/2.8.119 Version/10.54| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; VB_hottieregion; GTB7.1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; InfoPath.1; WinNT-PAI 28.07.2009; .NET CLR 2.0.50727; 979803803; Library2.02319)| +Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.1; InfoPath.2; .NET CLR 3.5.30729; .NET4.0C; .NET CLR 3.0.30729; 9768033603; control/5.00195; 886802803; 9877074903; 98770803; 666600503703; 699903603; 668609703; 97880603; 988703403803; 79680603; 79680703; 66960055603; 79680108603; 887803803; 97680443903; 87890377603; 8789026903; 6969014803; 87890703; 78690791703; 99760603; 9769030803; 78790603; 877907703; 88780603; 798805991903; 887804458603)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; FunWebProducts; GTB7.1; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; SRS_IT_E879027EBD765C5230AD90; .NET4.0C; BRI/1; 7978090803; ver:2.00241; 97990603; 979807259803; 997601703; 7899084603; 8898077803; 96690903; 88780803; 7899002603; 9986016703; 977901194903; 798809079703; 786901803; 998608903; 88980903; 979904703; 9788072703; 886806303703; 669605760603; 97980594903; 7889065803; 797803803; 6| +Cydia/0.9 CFNetwork/485.13.9 Darwin/11.0.0| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; Sky Broadband; GTB7.1; SeekmoToolbar 4.8.4; Sky Broadband; Sky Broadband; AskTbBLPV5/5.9.1.14019)| +Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; BOLT/2.690) AppleWebKit/534.6 (KHTML, like Gecko) Version/5.0 Safari/534.6.3| +Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; BOLT/2.680) AppleWebKit/534.6 (KHTML, like Gecko) Version/5.0 Safari/534.6.3| +AppEngine-Google; (+http://code.google.com/appengine; appid: domotoast-proxy)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB7.1; InfoPath.3; AskTbFWV5/5.12.2.16749)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; FunWebProducts; GTB7.1; InfoPath.2; BRI/1; BRI/2)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; GTB7.1; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; MAPB; .NET4.0C; InfoPath.2)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729); DMBrowser: f0215e2b-eb35-4cd1-8662-aa12ec8758ef| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; FunWebProducts; GTB6.6; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30618; AskTbIJBME/5.11.3.15590; 78690773903; Library1.00164)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SIMBAR={A4105742-BEFE-40FF-BC15-29D6915F8300}; SLCC1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.5.30729; .NET CLR 3.0.30618; .NET4.0C)| +Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.5401; Windows NT 6.1; WOW64; Trident/4.0; PicMorphSearchToolbar 1.2; FunWebProducts; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; CPDTDF; .NET4.0C; BRI/1; BRI/2; AskTbMP3R7/5.12.2.16749)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB7.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; ShopperReports 3.0.489.0; SRS_IT_E879027FB176555632A995; yie8)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729); DMBrowser: af5176c1-b768-4348-9c57-38a598bc0ad7| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; GTB7.1; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.30618; InfoPath.2; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; .NET CLR 3.5.30729)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; GTB7.1; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.30618; InfoPath.2; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; .NET CLR 3.5.30729)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; FunWebProducts; GTB7.1; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30618; InfoPath.2; AskTbFWV5/5.12.2.16749; .NET4.0C)| +Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.1; AOLBuild 4334.5012; Windows NT 5.1; GTB7.0; .NET CLR 1.1.4322; Windows-Media-Player/10.00.00.3990)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; GTB7.1; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30618; .NET4.0C; AskTbBT4/5.12.2.16749)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET4.0C; .NET4.0E; .NET CLR 3.5.30729; .NET CLR 3.0.30729); DMBrowser: 53aa9341-6d81-494a-a2b2-5daaaaa7661a| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; BTRS7391; GTB7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; eSobiSubscriber 2.0.4.16; MAAR; .NET4.0C)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SIMBAR={D20B426C-84DF-11E0-80E5-1C7508C85D85}; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; MAAR; .NET4.0C; AskTbGLSV5/5.9.1.14019)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; GTB7.1; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; OfficeLiveConnector.1.4; OfficeLivePatch.1.3; .NET4.0C; InfoPath.3; BRI/1; BRI/2)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SearchToolbar 1.1; InfoPath.1; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; yie8; XF_mmhpset)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; GTB7.1; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; AskTbPSI/5.12.2.16749; BO1IE8_v1;ENUS)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; chromeframe/13.0.782.112; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30618; .NET4.0C)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB6; FunWebProducts; BTRS26539; InfoPath.1; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; msn OptimizedIE8;ENUS; AskTB5.6)| +Mozilla/4.0 (compatible; MSIE 8.0; AOL 9.0; AOLBuild 4184.5450; Windows NT 5.1; Trident/4.0; GTB7.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; NET_mmhpset)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB6; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; InfoPath.2; AskTbLMW2/5.12.2.16749)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; SearchToolbar 1.2; .NET CLR 1.1.4322; IEMB3; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; Dealio Toolbar 3.4)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; GTB6; Sky Broadband; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 1.1.4322; .NET CLR 3.5.30729)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; GTB7.1; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; OfficeLiveConnector.1.5; OfficeLivePatch.1.3; .NET4.0C; InfoPath.2; .NET CLR 1.1.4322)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SearchToolbar 1.2; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; HPNTDF; .NET4.0C; BRI/1; InfoPath.2; BRI/2)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SearchToolbar 1.2; BTRS6253; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.30729; .NET4.0C; .NET CLR 3.0.30729; yie8)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; chromeframe/13.0.782.112; yie8)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; (R1 1.6); .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; AskTbSTC3-SRS/5.12.2.16752; yie8)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; GTB7.1; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; eSobiSubscriber 2.0.4.16; .NET4.0C; InfoPath.2; AskTbMMG/5.12.2.16749)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB7.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; Media Center PC 3.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; AskTbFTB/5.11.3.15590)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.1; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; VER#4A#80836748566745484987484957; .NET4.0C)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; GTB7.1; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; VER#5B#80836750696745484948484849; InfoPath.3)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 1.1.4322; InfoPath.2; .NET CLR 3.5.30729; .NET CLR 3.0.30618; .NET4.0C; BRI/1; BRI/2; AskTbGAM4/5.12.2.16749)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; GTB6; .NET CLR 1.1.4322; InfoPath.1; .NET CLR 2.0.50727; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; AskTbFWV5/5.12.2.16749)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; FunWebProducts; .NET CLR 1.1.4322; .NET CLR 2.0.50727; FunWebProducts; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; yie8)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; FBSMTWB; .NET CLR 1.1.4322; InfoPath.1; SRS_IT_E8790776B776545030A995; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 2.0.50727; .NET4.0C; InfoPath.2)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; SearchToolbar 1.2; GTB7.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; AskTbWCL2/5.11.3.15590; .NET4.0C; .NET4.0E; ety8x_cfg)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729); DMBrowser: 2bfb6d5b-9f0b-4d4b-bd00-d6589a123acd| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; BTRS5591; FunWebProducts; GTB7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; AskTbNRO/5.12.2.16749; 969906853703; Library3.00152)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; WOW64; Trident/4.0; GTB7.1; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.21022; .NET CLR 3.5.30729; InfoPath.2; .NET CLR 3.0.30729; .NET4.0C; BRI/1; BRI/2; NET_mmhpset)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB7.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; msn OptimizedIE8;ENUS; AskTB5.6)| +Mozilla/4.0 (compatible; MSIE 8.0; AOL 9.6; AOLBuild 4340.5003; Windows NT 5.1; Trident/4.0; GTB6.6; .NET CLR 2.0.50727)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; GTB7.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 1.1.4322; .NET CLR 3.5.21022; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; yie8)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; GTB7.1; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; HPNTDF; .NET4.0C; BRI/1; AskTbOVO/5.12.2.16749)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 1.1.4322; .NET CLR 3.5.30729; .NET CLR 3.0.30729; IEMB3; .NET4.0C; BRI/1; yie8)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; FCTB100293; .NET CLR 1.1.4322; .NET4.0C; yie8)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET CLR 1.1.4322; .NET4.0C; BRI/1; AskTbAD2/5.12.2.16749; MALC)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; FunWebProducts; GTB7.1; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; HPDTDF; BRI/1; .NET4.0C; FunWebProducts; AskTbPPC/5.12.2.16749)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; EasyBits GO v1.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; BO2IE8_v1;ENUS)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB7.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; NET_mmhpset)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; GTB7.1; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 1.1.4322; .NET CLR 3.5.30729; .NET CLR 3.0.30618; AskTbFWV5/5.9.1.14019)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.2; BRI/1; AskTbARS/5.12.1.16460)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; FunWebProducts; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; WinNT-PAI 30.08.2009; MySpace;; yie8)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; BRI/1; BRI/2; BOIE8;ENUSMSCOM)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.1; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; MDDS; AskTbBCPA/5.12.2.16749)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; FunWebProducts; GTB7.1; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; AskTbAD2/5.9.1.14019)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; FunWebProducts; (R1 1.5); EasyBits GO v1.0; .NET CLR 1.1.4322)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB7.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; SDR6; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB6; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; 878906803)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; FunWebProducts; GTB7.1; SLCC1; .NET CLR 2.0.50727; .NAP 1.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; GTB7.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; eSobiSubscriber 2.0.4.16; .NET CLR 1.1.4322; OfficeLiveConnector.1.5; OfficeLivePatch.1.3)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SearchToolbar 1.2; GTB7.1; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30618; SRS_IT_E8790571BD765C5436AE93)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; PeoplePal 6.6; .NET CLR 3.5.30729; .NET CLR 3.0.30618; BRI/1) w:PACBHO60| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; CIBA; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.2; SE 2.X MetaSr 1.0)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; Comcast Install 1.0; GTB7.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; AskTbORJ/5.12.3.17451)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; PBSTB 1.2; GTB7.1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 1.0.3705; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; IE0006_ver1;EN_US)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB7.1; WinNT-PAI 15.08.2009; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; msn OptimizedIE8;ENUS)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; WOW64; Trident/4.0; FunWebProducts; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; MDDC; .NET CLR 3.5.30729; .NET CLR 3.0.30729; OfficeLiveConnector.1.5; OfficeLivePatch.1.3; .NET4.0C; AskTbUT2V5/5.12.2.16749)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.1; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; MDDS; .NET4.0C; AskTbAD3/5.12.2.16749; BRI/1)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3; Windows Live Messenger 15.4.3538.0513)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; BRI/2; AskTB5.5)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; GTB7.1; InfoPath.1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; AskTbARS/5.11.4.15711; .NET CLR 1.1.4322)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; EasyBits GO v1.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; MDDC; ShopperReports 3.0.497.0; SRS_IT_E8790570B4765D5436A997; .NET4.0C; AskTbFWV5/5.12.2.16749; InfoPath.3)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; SearchToolbar 1.2; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; AskTbWCL2/5.12.2.16749; .NAP 1.1)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; GTB7.1; EasyBits GO v1.0; SLCC1; .NET CLR 2.0.50727; MDDC; .NET CLR 3.5.30729; .NET CLR 3.0.30729)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; GTB7.0; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; yie8; AskTB5.6)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; CMDTDF; AskTbORJ/5.12.3.17451)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; GTB7.1; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; VER#5B#80836750696745484948484849)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; FunWebProducts; GTB7.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; AskTbFWV5/5.12.2.16749; AskTB)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; PeoplePal 7.0; .NET CLR 1.1.4322; .NET CLR 3.5.30729; .NET CLR 3.0.30618; InfoPath.1; .NET4.0C)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; HPDTDF; InfoPath.2; .NET CLR 1.1.4322; .NET4.0C; 887806664703; compat/4.1.00302)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; SU 3.28; GTB7.1; .NET CLR 2.0.50727; FunWebProducts; AskTbFWV5/5.12.2.16749; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; yie8)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; MS-RTC LM 8; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C)| +Mozilla/4.0 (compatible; MSIE 8.0; AOL 9.1; AOLBuild 4334.5012; Windows NT 5.1; Trident/4.0; FunWebProducts; GTB7.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; MDDC; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; VER#Z9#80837689486745485080484950; .NET4.0C)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; Tablet PC 2.0; .NET CLR 3.5.30729; OfficeLiveConnector.1.5; OfficeLivePatch.1.3; .NET4.0C; .NET CLR 3.0.30729; BRI/1; BRI/2)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Trident/4.0; FunWebProducts; GTB6.6; SLCC1; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 1.1.4322; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; BRI/1; FDM)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB7.0; .NET CLR 2.0.50727; InfoPath.2; InfoPath.1)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SearchToolbar 1.2; GTB6.4; FunWebProducts; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; eSobiSubscriber 2.0.4.16; .NET4.0C; FunWebProducts; AskTbFWV5/5.12.2.16749)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB7.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; MS-RTC LM 8; Zune 4.7; InfoPath.3; BRI/2; .NET4.0C)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.0.3705; Media Center PC 4.0; .NET CLR 1.1.4322; InfoPath.1; BOIE8;ENUSMSCOM)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; GTB7.1; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; FDM; .NET4.0E)| +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; chromeframe/13.0.782.112; SLCC1; .NET CLR 2.0.50727; .NET CLR 1.1.4322; InfoPath.2; MS-RTC LM 8; .NET CLR 3.0.30729)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB7.0; .NET CLR 2.0.50727; .NET CLR 1.1.4322; AskTbORJ/5.12.3.17451; yie8)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 3.1; AskTbORJ/5.12.3.17451; yie8)| +Mozilla/4.0 (compatible; MSIE 8.0; AOL 9.5; AOLBuild 4337.185; Windows NT 5.1; Trident/4.0; GTB7.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.50727; Media Center PC 4.0; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; AskTB5.6; BO1IE8_v1;ENUS)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB7.1; .NET CLR 3.0.04506.30; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.1; yie8)| +Mozilla/4.0 (compatible; MSIE 8.0; AOL 9.6; AOLBuild 4340.5004; Windows NT 5.1; Trident/4.0; FBSMTWB; GTB7.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; Media Center PC 4.0; .NET CLR 2.0.50727; InfoPath.1; SpamBlockerUtility 4.8.4; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; WinTSU 08.10.2009; yie8)| +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; FunWebProducts; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; FunWebProducts)| +Mozilla/5.0 (Linux; U; Android 2.2.1; fr-fr; GT-I9003 Build/FROYO) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)| +Mozilla/5.0 (Linux; U; Android 2.1-update1; ar-eg; MB525 Build/JRDNEM_U3_2.59.0) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17|http://uaprof.motorola.com/phoneconfig/MotoMB525/profile/MotoMB525.rdf +Nokia6085/2.0 (06.00) Profile/MIDP-2.0 Configuration/CLDC-1.1 nokia6085/UC Browser7.9.0.102/69/352 UNTRUSTED/1.0|http://nds1.nds.nokia.com/uaprof/N6085r100.xml +MOT-ROKR E2/R564_G_12.01.46P K1nDinuX Mozilla/4.0 (compatible; MSIE 6.0; Linux; Motorola ROKR E2; 781) Profile/MIDP-2.0 Configuration/CLDC-1.1 Opera 8.50 [es-LA]| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[7658912216] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[2187703392] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.3; SAMSUNG-SGH-I997 Build/GINGERBREAD)| +Dalvik/1.4.0 (Linux; U; Android 2.3.1; TM-7022 Build/GINGERBREAD)|http://wap.sonyericsson.com/UAprof/LT15iR301.xml +NokiaX2-01/5.0 (07.10) Profile/MIDP-2.1 Configuration/CLDC-1.1 nokiax2-01/UC Browser7.4.0.65/69/352 UNTRUSTED/1.0|http://nds1.nds.nokia.com/uaprof/NokiaX2-01r100.xml +Blackberry 9300/6.0.0.668 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/168|http://www.blackberry.net/go/mobile/profiles/uaprof/9300_umts/5.0.0.rdf +Mozilla/5.0 (Linux; U; Android 2.2.1; fr-fr; GT-S5570-ORANGE/S5570BVKE2 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://gsm.lge.com/html/gsm/P990-M3-D2.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.12168/26.984; U; en) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Symbian/3; Series60/5.2 NokiaE7-00/020.031; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.3.1.12 Mobile Safari/533.4 3gpp-gba|http://nds1.nds.nokia.com/uaprof/NE7-00r100.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; fr_FR) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/BouyguesTelecom;FBID/phone;FBLC/fr_FR;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.2.1; fr-fr; LG-P500 Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://gsm.lge.com/html/gsm/P990-M3-D2.xml +Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/ADR-1110071847; U; pt-BR) Presto/2.9.201 Version/11.50|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +LG-GW300/V100 Obigo/WAP2.0 Profile/MIDP-2.0 Configuration/CLDCgsm.lge.com/html/gsm/LG-GW300.xml|http://gsm.lge.com/html/gsm/LG-GW300.xml +Dalvik/1.1.0 (Linux; U; Android v1.02_14.13-M-2011.01.10; RK2818 Build/ECLAIR)| +Mozilla/5.0 (Linux; U; Android 2.1-update1; fr-fr; E130 Build/ERE27) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[2703661933] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +LG-LG511C/1.0[TFXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX] Mozilla/5.0(compatible; Teleca Q7; BMP 1.0.1; U; en) 240X400 LGE LG-LG511C Profile/MIDP-2.1 Configuration/CLDC-1.1| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; tr_TR) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/2; FBCR/VODAFONETR;FBID/phone;FBLC/tr_TR;FBSF/2.0]| +Mozilla/4.0 (compatible; MSIE 6.0; Windows CE; IEMobile 7.6) Vodafone/1.0/HTC_Kaiser/1.56.162.5|http://www.htcmms.com.tw/gen/Kaiser-1.0.xml +Dalvik/1.1.0 (Linux; U; Android 2.1-update1; E400 Build/ECLAIR)|http://wap1.huawei.com/uaprof/HuaweiU8230v100WCDMAEclair.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.1;FBSS/2; FBCR/Carrier;FBID/phone;FBLC/en_US;FBSF/2.0]| +NokiaC1-01/2.0 (05.45) Profile/MIDP-2.1 Configuration/CLDC-1.1 Opera/9.60 (J2ME/MIDP;Opera Mini/5.2.13337.MTN.REMod.by.Andrewxy/503; U; en)Presto/2.2.0 UNTRUSTED/1.0| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.1;FBSS/1; FBCR/AT&T;FBID/phone;FBLC/en_US;FBSF/1.0]| +Mozilla/5.0 (Linux; U; Android 2.3.3; en-us; SonyEricssonST15i Build/4.0.A.2.377) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[9032407354] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (SAMSUNG; SAMSUNG-GT-S8530/S8530XEJK6; U; Bada/1.2; fr-fr) AppleWebKit/533.1 (KHTML, like Gecko) Dolfin/2.2 Mobile WVGA SMM-MMS/1.2.0 NexPlayer/3.0 profile/MIDP-2.1 configuration/CLDC-1.1 OPN-B|http://wap.samsungmobile.com/uaprof/GT-S8530_3G.rdf +MOT-K3/99.41.05R BER2.2 Mozilla/4.0 (compatible; MSIE 6.0; 12163189) Profile/MIDP-2.0 Configuration/CLDC-1.1 Opera 8.00 [ar]|http://motorola.handango.com/phoneconfig/K3/Profile/K3.rdf +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/1; FBCR/OrangeUK;FBID/phone;FBLC/en_US;FBSF/1.0]| +LG-GU295/V10i; Mozilla/5.0 (Profile/MIDP-2.0 Configuration/CLDC-1.1; Opera Mini/att/4.2.15957; U; es|http://gsm.lge.com/html/gsm/LG-GU295.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.1;FBSS/1; FBCR/T-MobileUK;FBID/phone;FBLC/en_US;FBSF/1.0]| +MQQBrowser/Mini2.2 (Nokia2690/10.10)| +Mozilla/5.0 (Series40; NokiaX3-00/03.60; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/1.4.0.34.8|http://nds1.nds.nokia.com/uaprof/NX3-00r100.xml +Mozilla/5.0 (Symbian/3; Series60/5.2 Nokia500/010.031; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.3.1.37 Mobile Safari/533.4 3gpp-gba| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; T3 Build/GRJ22)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.4; MB855 Build/4.5.1A-1_SUN-128)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Nokia6680/1.0 (5.04.07) SymbianOS/8.0 Series60/2.6 Profile/MIDP-2.0 Configuration/CLDC-1.1/UC Browser7.8.0.95/27/351|http://nds1.nds.nokia.com/uaprof/N6680r100.xml +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[8035218222] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +nokia6303classic/08.90; Opera/9.50 (J2ME/MIDP; Opera Mini/4.1.13961/546; de; U; ssr)|http://nds1.nds.nokia.com/uaprof/N6303classicr100.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.5; YP-G1 Build/GINGERBREAD)| +Blackberry 8350i/4.6.1.278 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/317| +Nokia7230/5.0 (09.83) Profile/MIDP-2.1 Configuration/CLDC-1.1 nokia7230/UC Browser7.9.0.102/70/352|http://nds1.nds.nokia.com/uaprof/N7230r100.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.7; HD2 Build/GRI40)| +Dalvik/1.4.0 (Linux; U; Android 2.3.3; SBM006SH Build/S0018)| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[7154046673] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0;FBBV/4000.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/1; FBCR/AT| +Dalvik/1.4.0 (Linux; U; Android 2.3.5; Xperia X8 Build/SEMC V3)| +Dalvik/1.4.0 (Linux; U; Android 2.3.3; LG-P500 Build/AGA-ROM)| +Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NOKIAN95 8GB/1.0; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413 Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NOKIAN95 8GB/1.0; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413 Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NOKIAN95 8GB/1.0; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413 Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NOKIAN95 8GB/1.0; |http://nds1.nds.nokia.com/uaprof/NN95-1r100.xml +Mozilla/5.0 (Linux; U; Android 2.3.3; fi-fi; HTC_WildfireS_A510e Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG76/ua-profile.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.10222/26.984; U; ar) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/1; FBCR/vodafoneUK;FBID/phone;FBLC/en_US;FBSF/1.0]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.1;FBBV/4010.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/OrangeUK;FBID/phone;FBLC/en_US;FBSF/2.0]| +Dalvik/1.4.0 (Linux; U; Android 2.3.3; SBM006SH Build/S0038)| +Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8J2 Safari/528.16 Kikin/1.5.0| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[2693482802] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +SAMSUNG-C5212/C5212JPJK2 NetFront/3.4 Profile/MIDP-2.0 Configuration/CLDC-1.1|http://wap.samsungmobile.com/uaprof/C5212.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.18154/26.984; U; tr) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8J2 Safari/525.20| +Mozilla/5.0 (Linux; U; Android 2.2.2; zh-cn; Dell Streak Build/FRG83G) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.2; fr-fr; HTC Desire Build/FRF91) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)| +LG-KS660 Teleca/WAP2.0 M•ÀÀDP-2.0/CLDC-1.1|http://gsm.lge.com/html/gsm/LG-KS660.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_1 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.1;FBSS/2; FBCR/Etisalat;FBID/phone;FBLC/en_US;FBSF/2.0]| +Dalvik/1.4.0 (Linux; U; Android 2.3.7; GT540 Build/GRI40)|http://gsm.lge.com/html/gsm/GT540_M6_D2_CL.xml +Dalvik/1.2.0 (Linux; U; Android 2.2.1; Milestone Build/R.U.R.1920)|http://uaprof.motorola.com/phoneconfig/motoa853/Profile/motoa853.rdf +Mozilla/5.0 (Linux; U; Android 2.1-update1; en-au; MB511 Build/RUTEM_U3_01.14.6) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; it_IT) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.5;FBSS/1; FBCR/Carrier;FBID/phone;FBLC/it_IT;FBSF/1.0]| +Dalvik/1.2.0 (Linux; U; Android 2.2.1; XT720 Build/STSKT_N_79.33.50R)|http://gsm.lge.com/html/gsm/P990-M3-D2.xml +Dalvik/1.2.0 (Linux; U; Android 2.2.2; GSmart G1310 Build/FRG83G)|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.3; ST18a Build/4.0.A.2.368)| +Dalvik/1.4.0 (Linux; U; Android 2.3.7; SPH-D700 Build/GRJ22)|http://device.sprintpcs.com/Samsung/SPH-D700/DI07.rdf +SonyEricssonW395/R1FB Browser/OpenWave/1.0 Profile/MIDP-2.1 Configuration/CLDC-1.1, SonyEricssonW395/R1FB Browser/OpenWave/1.0 Profile/MIDP-2.1 Configuration/CLDC-1.1, SonyEricssonW395/R1FB Browser/OpenWave/1.0 Profile/MIDP-2.1 Configuration/CLDC-1.1, SonyEricssonW395/R1FB Browser/OpenWave/1.0 Profile/MIDP-2.1 Configuration/CLDC-1.1, SonyEricssonW395/R1FB Browser/OpenWave/1.0 Profile/MIDP-2.1 Configuration/CLDC-1.1, SonyEricssonW395/R1FB Browser/OpenWave/1.0 Profile/MIDP-2.1 Configuration/CLDC-1.1, SonyEric|http://www.sonyericsson.com/downloads/W395R101.xml +Dalvik/1.1.0 (Linux; U; Android 2.1-update1; MB511 Build/RUTLA_U3_00.60.101)| +Mozilla/5.0 (Linux; U; Android 2.1-update1; ar-eg; HTC Magic Build/ERE27) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17|http://www.google.com/oha/rdf/ua-profile-kila.xml +Mozilla/4.0 SonyEricssonK850iv/R1CA|http://wap.sonyericsson.com/UAprof/K850iR101.xml +SonyEricssonT700/R3EF Browser/NetFront/3.4 Profile/MIDP-2.1 Configuration/CLDC-1.1 JavaPlatform/JP-8.3.3|http://wap.sonyericsson.com/UAprof/T700R101.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.7; A953 Build/GWK74)| +Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NOKIAN95 8GB/1.0; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413 Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NOKIAN95 8GB/1.0; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413 Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NOKIAN95 8GB/1.0; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413 Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NOKIAN95 8GB/1.0; |http://nds1.nds.nokia.com/uaprof/NN95-1r100.xml +Mozilla/5.0 (Linux; U; Android 2.3.5; en-us; Desire HD Build/MIUI) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://uaprof.vtext.com/adr62k/adr62k.xml +Mozilla/5.0 (Linux; U; Android 1.1.5; fr-fr; A101B2-LZ Build/ECLAIR) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17| +Opera/9.80 (J2ME/MIDP; Opera Mini/5.3521/26.984; U; tr) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; fr_FR) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/2; FBCR/TELUS;FBID/phone;FBLC/fr_FR;FBSF/2.0]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.2.1;FBSS/1; FBCR/Telekom.de;FBID/phone;FBLC/de_DE;FBSF/1.0]| +Mozilla/5.0 (SAMSUNG; SAMSUNG-GT-S8500/S8500JPJF4; U; Bada/1.0; fr-fr) AppleWebKit/533.1 (KHTML, like Gecko) Dolfin/2.0 Mobile WVGA SMM-MMS/1.2.0 OPN-B|http://wap.samsungmobile.com/uaprof/GT-S8500_3G.rdf +Dalvik/1.1.0 (Linux; U; Android 2.1-update1; MB502 Build/BASEM_U3_01.12.4)| +Dalvik/1.2.0 (Linux; U; Android 2.2.1; GT-S5570B Build/FROYO)|http://gsm.lge.com/html/gsm/P990-M3-D2.xml +Mozilla/5.0 (Linux; U; Android 2.3.5; en-gb; GT-I9000 Build/MIUI) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://wap.samsungmobile.com/uaprof/GT-i9000.xml +Opera/9.80 (Windows Mobile; Opera Mini/5.1.21594/26.984; U; pt) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[9083397752] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.3.24492/26.984; U; en) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.1.14287/26.984; U; id) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.16007/26.984; U; en) Presto/2.8.119 Version/10.54| +Opera/9.80 (Android 1.6; Linux; Opera Mobi/ADR-1110071847; U; en) Presto/2.9.201 Version/11.50| +Mozilla/5.0 (iPod touch; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPod4,1;FBMD/iPod touch;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; ar_AR) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.1;FBBV/4010.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/1; FBCR/Vodafone;FBID/phone;FBLC/ar_AR;FBSF/1.0]| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; GT-S5670 Build/GINGERBREAD)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Mozilla/5.0 (SymbianOS/9.2; U; Series60/3.1 NokiaE63-3/200.21.012; Profile/MIDP-2.0 Configuration/CLDC-1.1) AppleWebKit/413 (KHTML, like Gecko) Safari/413|http://nds1.nds.nokia.com/uaprof/NE63-3r100.xml +Opera/9.80 (Android 3.2.1; Linux; Opera Tablet/ADR-1110071847; U; en) Presto/2.9.201 Version/11.50| +Opera/9.80 (Android 2.2; Linux; Opera Mobi/ADR-1110071847; U; nl) Presto/2.9.201 Version/11.50| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[3046140517] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (Linux; U; Android 2.3.3; sk-sk; HTC_WildfireS_A510e Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG76/ua-profile.xml +BlackBerry8310/4.5.0.187 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/161|http://www.blackberry.net/go/mobile/profiles/uaprof/8310/4.2.2.rdf +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0;FBBV/4000.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/2; FBCR/OrangeUK;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.2.2; de-de; MB860 Build/Blur_Version.4.4.20.MB860.Retail.en.DE Flex/P023) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.1;FBBV/4010.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.2.1;FBSS/2; FBCR/vodafoneUK;FBID/phone;FBLC/en_US;FBSF/2.0]| +Dalvik/1.4.0 (Linux; U; Android 2.3.7; IDEOS X5 Build/GRJ22)| +gt-s5233w/UC Browser7.9.0.102/69/444 UNTRUSTED/1.0| +Mozilla/5.0 (Linux; U; Android 2.3.4; hu-hu; GT-S5570 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.14386/26.984; U; ar) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.12814/26.984; U; es) Presto/2.8.119 Version/10.54| +Blackberry 9700/5.0.0.862 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/609|http://www.blackberry.net/go/mobile/profiles/uaprof/9700_umts/5.0.0.rdf +sgh-f480/UC Browser7.9.0.102/69/352 UNTRUSTED/1.0| +Mozilla/5.0 (Linux; U; Android 2.3.2; pl-pl; SonyEricssonR800iv Build/3.0.A.2.184) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Dalvik/1.2.0 (Linux; U; Android 2.2.1; Milestone Build/SHOLS_U2_05.26.4)|http://uaprof.motorola.com/phoneconfig/motoa853/Profile/motoa853.rdf +Mozilla/5.0 (iPod touch; U; CPU iPhone OS 4_2_1 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPod4,1;FBMD/iPod touch;FBSN/iPhone OS;FBSV/4.2.1;FBSS/2; FBCR/;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.3.3; en-fr; HTC_DesireS_S510e Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG88/ua-profile.xml +Dalvik/1.2.0 (Linux; U; Android 2.2.2; LG-KU3700 Build/FRG83G)|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/2; FBCR/vodaAU;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.3.3; en-id; Desire HD Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG88/ua-profile.xml +Mozilla/5.0 (Series40; NokiaC2-02/06.96; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/1.0.2.26.8| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; en-gb) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5 Cydia/1.1.2 CyF/550.58| +Nokia6310i/1.0 (4.06) Profile/MIDP-1.0 Configuration/CLDC-1.0|http://nds.nokia.com/uaprof/N6310r100.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.4; ME525+ Build/4.5.2-109_DHT-17)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Opera/9.80 (Android 2.3.1; Linux; Opera Mobi/ADR-1110071847; U; fr) Presto/2.9.201 Version/11.50|http://wap.sonyericsson.com/UAprof/LT15iR301.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; sv_SE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.1;FBBV/4010.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/2; FBCR/TELIA;FBID/phone;FBLC/sv_SE;FBSF/2.0]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone4,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/O2;FBID/phone;FBLC/en_US;FBSF/2.0]| +Opera/9.80 (Android 2.2; Linux; Opera Mobi/ADR-1110071847; U; it) Presto/2.9.201 Version/11.50| +Mozilla/5.0 (Linux; U; Android 2.3.6; ko-kr; SHV-E160S Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; HTC Desire Build/GRK39F) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://uaprof.vtext.com/adr62k/adr62k.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/Vodafone.de;FBID/phone;FBLC/de_DE;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.3.3; ko-kr; SHW-M250S Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 NAVER(inapp; search; 101; 3.0.2)| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; SHW-M250L Build/4.5.2A-KT-75)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Mozilla/5.0 (Linux; U; Android 1.6; en-us; E10i Build/1.1.A.0.8) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1|http://wap.sonyericsson.com/UAprof/E10iR102.xml +Blackberry9780/6.0.0.294 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/-1|http://www.blackberry.net/go/mobile/profiles/uaprof/9780/6.0.0.rdf +Mozilla/5.0 (Linux; U; Android 2.3.3; en-au; SonyEricssonST18i Build/4.0.A.2.368) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.2.1;FBSS/1; FBCR/OrangeUK;FBID/phone;FBLC/en_US;FBSF/1.0]| +Mozilla/5.0 (iPod touch; U; CPU iPhone OS 4_2_1 like Mac OS X; bg_BG) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/3.5a;FBBV/3500;FBDV/iPod3,1;FBMD/iPod touch;FBSN/iPhone OS;FBSV/4.2.1;FBSS/1; FBCR/;FBID/phone;FBLC/bg_BG]| +Mozilla/5.0 (Linux; U; Android 2.3.3; en-nl; HTC Sensation Z710e Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_4 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.4;FBSS/2; FBCR/Carrier;FBID/phone;FBLC/de_DE;FBSF/2.0]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.5;FBSS/1; FBCR/O2;FBID/phone;FBLC/en_US;FBSF/1.0]| +Mozilla/5.0 (Linux; U; Android 2.1-update1; en-in; SonyEricssonU20i Build/2.0.2.A.0.24) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17|http://wap.sonyericsson.com/UAprof/U20iR202.xml +Mozilla/5.0 (Linux; U; Android 2.2.1; ja-jp; SBM003SH Build/S1900) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://gsm.lge.com/html/gsm/P990-M3-D2.xml +NokiaX3-00/5.0 (08.54) Profile/MIDP-2.1 Configuration/CLDC-1.1 nokiax3-00/UC Browser7.9.0.102/70/352 UNTRUSTED/1.0|http://nds1.nds.nokia.com/uaprof/NX3-00r100.xml +Mozilla/5.0 (Linux; U; Android 2.3.3; ko-kr; HTC_S710E Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Opera/9.80 (iPhone; Opera Mini/6.1.15738/26.984; U; nb) Presto/2.8.119 Version/10.54| +Dalvik/1.4.0 (Linux; U; Android 2.3.5; Droid Build/MIUI-1.9.16.0-SHOLES-EN)| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.22892/26.984; U; en) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.9751/26.984; U; id) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.2; fr-fr; LG-P500 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.1-update1; vi-vn; X10i Build/2.1.A.0.435) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)|http://wap.sonyericsson.com/UAprof/X10iR201.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.1;FBBV/4010.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.2.1;FBSS/2; FBCR/Carrier;FBID/phone;FBLC/de_DE;FBSF/2.0]| +Dalvik/1.1.0 (Linux; U; Android 2.1-Strabors-Mod-2.1.3; ZTE Racer Build/ERE27)| +Opera/9.80 (Android 2.3.7; Linux; Opera Mobi/ADR-1110071847; U; de) Presto/2.9.201 Version/11.50| +Mozilla/5.0 (Series40; Nokia5310XpressMusic/10; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/1.4.0.34.8|http://nds1.nds.nokia.com/uaprof/N5310XpressMusicr100.xml +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; HTC Aria Build/FRG83G) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 androidAppVersion/2.1 AndroidWebkitWrapper|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 ( ; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5| +Mozilla/5.0 (Linux; U; Android 2.3.5; en-us; HTC Glacier Build/GRJ90) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Dalvik/1.4.0 (Linux; U; Android 2.3.6; Nexus One Build/MOG)| +iPhone - Safari 528.16 (iPhone OS 3.0)| +Mozilla/5.0 (Linux; U; Android 2.3.3; de_de) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Ninesky/1.7.0 Safari/533.1| +Mozilla/5.0 (iPad; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0;FBBV/4000.0;FBDV/iPad1,1;FBMD/iPad;FBSN/iPhone OS;FBSV/4.3.3;FBSS/1; FBCR/;FBID/tablet;FBLC/en_US;FBSF/1.0]| +Dalvik/1.2.0 (Linux; U; Android 2.2; X06HT Build/FRF91)| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.14881/26.984; U; es) Presto/2.8.119 Version/10.54| +Nokia2690/10.10| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/3.5a;FBBV/3500;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/1; FBCR/Telekom.de;FBID/phone;FBLC/de_DE]| +Mozilla/5.0 (Linux; U; Android 2.1-update1; sr-rs; GT-I9000 Build/ECLAIR) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)|http://wap.samsungmobile.com/uaprof/GT-i9000.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.5; Desire HD Build/GRI40)|http://uaprof.vtext.com/adr62k/adr62k.xml +Mozilla/5.0 (Series40; Nokia5330-1d/06.88; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/1.4.0.34.8|http://nds1.nds.nokia.com/uaprof/N5330-1dr100.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.13227/26.984; U; en) Presto/2.8.119 Version/10.54| +Dalvik/1.2.0 (Linux; U; Android 2.2.2; MB525 Build/JEM_3.4.3-36-1.1)|http://uaprof.motorola.com/phoneconfig/MotoMB525/profile/MotoMB525.rdf +Dalvik/1.2.0 (Linux; U; Android 2.2.1; iDx7 Build/FROYO)|http://gsm.lge.com/html/gsm/P990-M3-D2.xml +SonyEricssonJ10i2/R7CA|http://wap.sonyericsson.com/UAprof/J10i2R101.xml +Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; Nexus One Build/GRJ71) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Dalvik/1.4.0 (Linux; U; Android 2.3.5; HTC Desire S Build/GRJ22)|http://uaprof.vtext.com/adr62k/adr62k.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.2;FBSS/2; FBCR/Telekom.de;FBID/phone;FBLC/de_DE;FBSF/2.0]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0_1 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.0.1;FBSS/2; FBCR/Telekom.de;FBID/phone;FBLC/de_DE;FBSF/2.0]| +Mozilla/5.0 (aYeN; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.1;FBBV/4010.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.5;FBSS/1; FBCR/3;FBID/phone;FBLC/en_US;FBSF/1.0]| +NokiaC1-01/2.0 (04.40) Profile/MIDP-2.1 Configuration/CLDC-1.1 nokiac1-01/UC Browser7.8.0.95/69/352 UNTRUSTED/1.0| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; DROID BIONIC Build/5.5.1_84_DBN-91-LaunchKit)| +Opera/9.80 (J2ME/MIDP; Opera Mini/5.22349/26.984; U; en) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; ar_AR) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/2; FBCR/ZainKW;FBID/phone;FBLC/ar_AR;FBSF/2.0]| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; GT-S5830D Build/GINGERBREAD)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +NokiaX3-00/5.0 (11.00) Profile/MIDP-2.1 Configuration/CLDC-1.1 nokiax3-00/UC Browser7.6.1.82/69/352 UNTRUSTED/1.0|http://nds1.nds.nokia.com/uaprof/NX3-00r100.xml +Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) 1Password/3.6.1/361005 (like Mobile/8C148 Safari/6533.18.5)| +NokiaC1-01/2.0 (05.40) Profile/MIDP-2.1 Configuration/CLDC-1.1 nokiac1-01/UC Browser7.9.0.102/70/352| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; FIH-FB0 Build/GRJ22)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.4; MB526 Build/4.5.1_128)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Mozilla/5.0 (Linux; U; Android 2.2.2; ko; LG-P970 Build/FRG83G) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 MMS/LG-Android-MMS-V1.0/1.2|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +gt-s5233s UNTRUSTED/1.0 UNTRUSTED/1.0| +Nokia5310XpressMusic/2.0 (10.10) Profile/MIDP-2.1 Configuration/CLDC-1.1 nokia5310xpressmusic/UC Browser7.0.0.41/69/352 UNTRUSTED/1.0|http://nds1.nds.nokia.com/uaprof/N5310XpressMusicr100.xml +Mozilla/5.0 (Linux; U; Android 2.3.4; ko-kr; LG-KU3700 Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 MMS/LG-Android-MMS-V1.0/1.2|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/1; FBCR/AT&T;FBID/phone;FBLC/en_US;FBSF/1.0]| +Mozilla/5.0 (Linux; U; Android 2.3.3; zh-tw; SonyEricssonR800i Build/3.0.1.A.0.145) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.3.4; da-us; pcdadr6350 Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.1.11313/26.984; U; es) Presto/2.8.119 Version/10.54| +Blackberry 9700/6.0.0.570 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/100|http://www.blackberry.net/go/mobile/profiles/uaprof/9700_umts/5.0.0.rdf +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.1;FBBV/4010.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.2;FBSS/2; FBCR/AT| +Dalvik/1.2.0 (Linux; U; Android 2.2.2; MB860 Build/OLYLA_U4_0.54.0_R01)| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/3.5a;FBBV/3500;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.2.1;FBSS/1; FBCR/Telekom.de;FBID/phone;FBLC/de_DE]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8L1 HPSwissKnife/4.0| +Mozilla/5.0 (Linux; U; Android 2.3.5; en-au; GT-I9100 Build/MIUI) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (iPad; U; CPU iPhone OS 4_3_4 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPad2,1;FBMD/iPad;FBSN/iPhone OS;FBSV/4.3.4;FBSS/1; FBCR/;FBID/tablet;FBLC/en_US;FBSF/1.0]| +Blackberry 9700/6.0.0.448 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/327|http://www.blackberry.net/go/mobile/profiles/uaprof/9700_umts/5.0.0.rdf +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[7408566616] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (Linux; U; Android 2.3.5; en-us; Droid Build/MIUI-1.10.7.0-SHOLES-EN) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.22228/26.984; U; sr) Presto/2.8.119 Version/10.54| +Dalvik/1.2.0 (Linux; U; Android 2.2.2; LG-P500h Build/FRG83)|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (BlackBerry; U; BlackBerry 9790; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0.473 Mobile Safari/534.11+| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.13067/26.984; U; es) Presto/2.8.119 Version/10.54| +BlackBerry9700/5.0.0.586 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/610|http://www.blackberry.net/go/mobile/profiles/uaprof/9700_umts/5.0.0.rdf +Dalvik/1.4.0 (Linux; U; Android 2.3.5; YP-G70 Build/GINGERBREAD)| +SonyEricssonK600i/R2BB Browser/SEMC-Browser/4.2 Profile/MIDP-2.0 Configuration/CLDC-1.1|http://wap.sonyericsson.com/UAprof/K600iR101.xml +Mozilla/5.0 (iPad; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPad1,1;FBMD/iPad;FBSN/iPhone OS;FBSV/4.3.3;FBSS/1; FBCR/;FBID/tablet;FBLC/en_US;FBSF/1.0]| +Mozilla/5.0 (Linux; U; Android 2.3.5; de-de; HTC HD2 Build/MIUI) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Opera/9.80 (J2ME/MIDP; Opera Mini/5.1.21566/26.984; U; pt) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/5.1.24321/26.984; U; es) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.3.3; ko-kr) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[7572012100] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.5; TripNMiUI Pyramid Build/S01031B.1.10.14-TripNRaVeR)| +Mozilla/5.0 (Linux; U; Android 2.3.3; en-gb; pcdadr6350 Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[8704947881] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (Linux; U; Android 3.2; ko-kr; SHW-M380W Build/HTJ85B) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13| +AppleCoreMedia/1.0.0.9A334 (iPod; U; CPU OS 5_0 like Mac OS X; en_us)| +Dalvik/1.4.0 (Linux; U; Android 2.3.7; SGH-I777 Build/GWK74)| +Dalvik/1.4.0 (Linux; U; Android 2.3.5; PG86100 Build/MIUI)| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-au; Liquid Metal Build/FRG83G) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://support.acer.com/UAprofile/Acer_S100_Profile.xml +Mozilla/5.0 (BlackBerry; U; BlackBerry 9810; en) AppleWebKit/534.11 (KHTML, like Gecko) Version/7.0.0.317 Mobile Safari/534.11| +Mozilla/5.0 (Linux; U; Android 2.2.2; ko-kr; SCH-i909 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9A334 Zite/1.2| +Opera/9.80 (J2ME/MIDP; Opera Mini/5.20952/26.984; U; es) Presto/2.8.119 Version/10.54| +Opera/9.50 (J2ME/MIDP; Opera Mini/4.2.19923/25.852; U; es)| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.1.13685/26.984; U; ar) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/2; FBCR/Telstra;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (m.arce02‰?´; U; CPU iPhone OS 4_3_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8G4 Safari/6533.18.5| +Mozilla/5.0 (Linux; U; Android 3.2; de-de; Sony Tablet S Build/THMAS11000) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[2012806883] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/5.18487/26.984; U; es) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.1.13907/26.984; U; es) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.3.2; ru-ru; SonyEricssonLT15i Build/3.0.A.2.184) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0_2 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.0.2;FBSS/2; FBCR/AT| +Opera/9.80 (BREW; Opera Mini/5.16/24.1029; U; en) Presto/2.5.25 480X800 LG VX11000H-U660| +Mozilla/5.0 (Linux; U; Android 2.3.4; es-es; MT11i Build/4.0.1.A.0.283) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Blackberry8520/5.0.0.681 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/298|http://www.blackberry.net/go/mobile/profiles/uaprof/8520_80211g/4.6.1.rdf +Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; SGH-I777 Build/GWK74) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.2.1;FBSS/2; FBCR/Carrier;FBID/phone;FBLC/de_DE;FBSF/2.0]| +Opera/9.80 (S60; SymbOS; Opera Mobi/SYB-1107071604; U; sr) Presto/2.8.149 Version/11.10| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.2;FBSS/2; FBCR/AT| +Opera/9.80 (Android 2.1-update1; Linux; Opera Mobi/ADR-1110071847; U; es-ES) Presto/2.9.201 Version/11.50|http://wap1.huawei.com/uaprof/HuaweiU8230v100WCDMAEclair.xml +BlackBerry9300/5.0.0.758 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/136|http://www.blackberry.net/go/mobile/profiles/uaprof/9300_umts/5.0.0.rdf +Mozilla/5.0 (Linux; U; Android 1.6; fr-fr; HTC Tattoo Build/DRC79) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1|http://www.htcmms.com.tw/Android/Common/Tattoo/ua-profile.xml +SAMSUNG-GT-C5010E/C5010EZHKE1 NetFront/3.5 Profile/MIDP-2.0 Configuration/CLDC-1.1| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[8068918312] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (BlackBerry; U; BlackBerry 9780; pl) AppleWebKit/534.8+ (KHTML, like Gecko) Version/6.0.0.576 Mobile Safari/534.8+|http://www.blackberry.net/go/mobile/profiles/uaprof/9780/6.0.0.rdf +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0;FBBV/4000.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.5;FBSS/1; FBCR/AT| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; Nexus One Build/MIUI)| +Opera/9.80 (BlackBerry; Opera Mini/4.3.25172/26.984; U; en) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; HTC Glacier Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 BingWeb/2.1.570.20110929| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.10247/26.984; U; tr) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.1-update1; nl-nl; GT-I5500 Build/ERE27) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)| +Opera/9.80 (J2ME/MIDP; Opera Mini/5.22371/26.984; U; en) Presto/2.8.119 Version/10.54n/10.54| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; ar_AR) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/Etisalat;FBID/phone;FBLC/ar_AR;FBSF/2.0]| +Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en-GB) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0.440 Mobile Safari/534.11+| +Mozilla/5.0 (iPad; U; CPU iPhone OS 4_3_1 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPad2,1;FBMD/iPad;FBSN/iPhone OS;FBSV/4.3.1;FBSS/1; FBCR/;FBID/tablet;FBLC/en_US;FBSF/1.0]| +Dalvik/1.5.1 (Linux; U; Android 3.2; tegav2 Build/HTJ85B)| +Dalvik/1.4.0 (Linux; U; Android 2.3.3; XT316 Build/GRI40)| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/3.5a;FBBV/3500;FBDV/iPhone1,2;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.0;FBSS/1; FBCR/AT| +Opera/9.80 (J2ME/MIDP; Opera Mini/5.22371/26.984; U; en) Presto/2.8.119 Version/10.54544| +Mozilla/5.0 (iPad; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPad2,2;FBMD/iPad;FBSN/iPhone OS;FBSV/5.0;FBSS/1; FBCR/vodafoneUK;FBID/tablet;FBLC/en_US;FBSF/1.0]| +Nokia6230/2.0 (03.15) Profile/MIDP-2.0 Configuration/CLDC-1.1 (compatible; GROUP_ID=PG2100-Fitel/VER=1.00/BROWSER=ObigoQ03C/TCPIP=1.00/PIAFS=3.02C/MELODY=F/PSID=075103571/PSNO= 115120901124)|http://nds1.nds.nokia.com/uaprof/N6230r100.xml +Opera/9.00 (Nintendo Wii; U; ; 1038-58; Wii Internet Channel/1.0; en)| +Mozilla/5.0 (Linux; U; Android 2.1-update1; en-sk; HTC_Wildfire_A3333 Build/ERE27) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17|http://www.htcmms.com.tw/Android/Common/Wildfire/ua-profile.xml +Mozilla/5.0 (Linux; U; Android 2.3.3; en-us; SonyEricssonSK17iv Build/4.0.A.2.335) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (P-DOG ;-); U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5| +Mozilla/5.0 (Linux; U; Android 2.3.3; de-de; SonyEricssonST15i Build/4.0.A.2.368) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Opera/9.80 (BlackBerry; Opera Mini/4.3.26549/26.984; U; en) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.3.3; ru-; DROID2 Build/4.5.1_57_DR2-31) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +BlackBerry9000/5.0.0.510 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/179|http://www.blackberry.net/go/mobile/profiles/uaprof/9000/4.6.0.rdf +Mozilla/5.0 (Linux; U; Android 2.3.3; en-bg; HTC_WildfireS_A510e Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG76/ua-profile.xml +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[4043302300] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.9800/26.984; U; es) Presto/2.8.119 Version/10.54| +Opera/9.80 (BlackBerry; Opera Mini/5.1.21216/26.984; U; en) Presto/2.8.119 Version/10.54| +Dalvik/1.4.0 (Linux; U; Android 2.3.5; HTC Sensation kingdroid v7 sense 3.5 Build/GRJ90)| +Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaC6-00.1/41.2.010; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.3.1.31 3gpp-gba| +Mozilla/5.0 (Linux; U; Android 3.0.1; en-gb; GtabComb Build/HRI66) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13| +NokiaN97/UC Browser7.9.0.102/50/351/UCWEB|http://nds1.nds.nokia.com/uaprof/NN97r100-2G.xml +Nokia7230/5.0 (10.82) Profile/MIDP-2.1 Configuration/CLDC-1.1 Mozilla/5.0 AppleWebKit/420 (KHTML, like Gecko) Safari/420|http://nds1.nds.nokia.com/uaprof/N7230r100.xml +Dalvik/1.5.1 (Linux; U; Android 3.2; streak7 Build/HTJ85B)| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; Galaxy5 Build/GRI40)|http://wap.samsungmobile.com/uaprof/GT-i5700.xml +Dalvik/1.2.0 (Linux; U; Android 2.2.2; Liquid Build/FRG83G)|http://support.acer.com/UAprofile/Acer_S100_Profile.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone1,2;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.1;FBSS/1; FBCR/OrangeUK;FBID/phone;FBLC/en_US;FBSF/1.0]| +Mozilla/5.0 (Linux; U; Android 2.3.4; da-dk; HTC Sensation Z710e Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Mozilla/5.0 (Linux; U; Android 2.2; zh-; GT-I9000 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://wap.samsungmobile.com/uaprof/GT-i9000.xml +Mozilla/5.0 (Linux; U; Android 2.2.2; es-us; SCH-M828C[2563053682] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (Linux; U; Android 1.6; es-us; T-Mobile myTouch 3G Build/DMD64) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1| +BlackBerry8900/5.0.0.1067 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/222|http://www.blackberry.net/go/mobile/profiles/uaprof/8900_80211g/4.6.1.rdf +Mozilla/5.0 (Linux; U; Android 2.3.4; ko-kr; GT-S5830L Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.18887/26.984; U; es) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.16402/26.984; U; fr) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (compatible; OSS/1.0; Chameleon; Linux) U9/R6632_G_81.11.1AI BER/2.0 Profile/MIDP-2.0 Configuration/CLDC-1.1| +Dalvik/1.4.0 (Linux; U; Android 2.3.5; M860 Build/GRJ90)| +Mozilla/5.0 (Linux; U; Android 2.3.3; de-at; SonyEricssonST18i Build/4.0.A.2.368) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.3.4; en-gb; GT-I9100G Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[5178030618] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[2055206767] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.2;FBSS/2; FBCR/Etisalat;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.3.3; en-us; DROID X2 Build/4.5.1_57_DX5-32) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Opera/9.80 (J2ME/MIDP; Opera Mini; U; es) Presto/2.8.119 Version/10.54119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.3.3; de-ch; HTC Vision Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Dalvik/1.5.0 (Linux; U; Android 3.0.1; Flashback 7.2 Build/HRI66)| +Mozilla/5.0 (Linux; U; Android 3.0.1; zh-tw; A501 Build/HRI66) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13| +Mozilla/5.0 (iPad; U; CPU iPhone OS 5_0 like Mac OS X; ar_AR) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPad1,1;FBMD/iPad;FBSN/iPhone OS;FBSV/5.0;FBSS/1; FBCR/Carrier;FBID/tablet;FBLC/ar_AR;FBSF/1.0]| +BlackBerry9000/5.0.0.743 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/205|http://www.blackberry.net/go/mobile/profiles/uaprof/9000/4.6.0.rdf +Mozilla/5.0 (iPad; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPad2,2;FBMD/iPad;FBSN/iPhone OS;FBSV/4.3.3;FBSS/1; FBCR/Carrier;FBID/tablet;FBLC/en_US;FBSF/1.0]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/1; FBCR/Telekom.de;FBID/phone;FBLC/de_DE;FBSF/1.0]| +LG-GW300/V100 Obigo/WAP2.0 Profile/MIDP-2.0 ConfiguraET_SessionId=haio0r232vbh0yfyiorxrrvl|http://gsm.lge.com/html/gsm/LG-GW300.xml +SAMSUNG-GT-B3210/1.0 Release/10.19.2009 Browser/NetFront3.5 Profile/MIDP-2.0 Configuration/CLDC-1.1/*MzU3Nzk3MDM5MTM2MzEy|http://wap.samsungmobile.com/uaprof/GT-B3210UAProf.xml +Opera/9.80 (iPhone; Opera Mini/6.1.15738/26.984; U; ar) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.2.2; es-us; SCH-M828C[2242450905] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/2; FBCR/Etisalat;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.3.3; fi-fi; Desire HD Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG88/ua-profile.xml +Mozilla/5.0 (Series40; NokiaC3-00/08.65; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/1.4.0.34.8|http://nds1.nds.nokia.com/uaprof/NokiaC3-00r100.xml +RT320X240/M.RF4700201.M01001.V1.0/WAP2.0 Profile/MIDP-2.0 Configuration/CLDC-1.0 RT320X240/M.RF4700201.M01001.V1.0/WAP2.0 Profile/MIDP-2.0 Configuration/CLDC-1.0| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/Etisalat;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.3.5; en-us; MB865 Build/5.5.1-175_EDFFW1-16) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (iPad; U; CPU OS 3_2_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B500 Installous| +Dalvik/1.2.0 (Linux; U; Android 2.2.2; MB525 Build/3.4.2-108_JDNL-2_R01)|http://uaprof.motorola.com/phoneconfig/MotoMB525/profile/MotoMB525.rdf +BlackBerry9100/5.0.0.783 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/611|http://www.blackberry.net/go/mobile/profiles/uaprof/9100/4.6.0.rdf +Opera/9.80 (iPad; Opera Mini/6.1.15738/26.984; U; ru) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.9800/26.984; U; en) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Welcome 2 Stunnaville; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; da_DK) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/3.5a;FBBV/3500;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/2; FBCR/TELIA;FBID/phone;FBLC/da_DK]| +Mozilla/5.0 (Linux; U; Android 2.2.2; es-us; MB612 Build/KRNS-X4-1.1.10) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (Linux; U; Android 2.1-update1; fr-fr; GT-I5800 Build/ECLAIR) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)|http://wap.samsungmobile.com/uaprof/GT-i5800.xml +Dalvik/1.2.0 (Linux; U; Android 2.2.1; ckt16_a10y Build/MASTER)|http://gsm.lge.com/html/gsm/P990-M3-D2.xml +Opera/9.80 (BlackBerry; Opera Mini/5.1.22303/26.984; U; ar) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 1.6; fr-fr; X10i Build/R2BA026) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)|http://wap.sonyericsson.com/UAprof/X10iR101.xml +Mozilla/5.0 (Linux; U; Android 2.2.2; zh-cn; SGH-T589R Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (Linux; U; Android 1.6; fr-fr; E130 Build/Donut) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)| +Opera/9.80 (Android 2.2; Linux; Opera Tablet/ADR-1110071847; U; it) Presto/2.9.201 Version/11.50| +Mozilla/5.0 (Linux; U; Android 2.3.3; ms-my; SonyEricssonSK17a Build/4.0.A.2.335) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[5095461741] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +SAMSUNG-GT-S3653/S3653JPJA2 SHP/VPP/R5 Jasmine/1.0 Nextreaming SMM-MMS/1.2.0 profile/MIDP-2.1 configuration/CLDC-1.1|http://wap.samsungmobile.com/uaprof/GT-S3653.rdf +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.5;FBSS/2; FBCR/Mobinil;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 1.6; de-de; SonyEricssonE10i Build/1.2.A.1.174) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1|http://wap.sonyericsson.com/UAprof/E10iR102.xml +Dalvik/1.2.0 (Linux; U; Android 2.2.1; A853 Build/SHLA_U2_05.12.0)| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/1; FBCR/Etisalat;FBID/phone;FBLC/en_US;FBSF/1.0]| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.1.13907/26.984; U; ru) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; IDEOS X5 Build/HuaweiU8800Pro) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.3.26550/26.984; U; en) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.21648/2644; U; en) Presto/2.2.0Opera Mini/att/4.2.15814; U; en| +NokiaC2-01/5.0 (10.50) Profile/MIDP-2.1 Configuration/CLDC-1.1 nokiac2-01/UC Browser7.8.0.95/70/350|http://nds1.nds.nokia.com/uaprof/NC2-01r100.xml +Dalvik/1.2.0 (Linux; U; Android 2.2; Liquid Metal Build/MASTER)|http://support.acer.com/UAprofile/Acer_S100_Profile.xml +Nokia6630/1.0 (4.03.38) SymbianOS/8.0 Series60/2.6 Profile/MIDP-2.0 Configuration/CLDC-1.1/UC Browser7.9.0.102/27/351/UCWEB|http://nds1.nds.nokia.com/uaprof/N6630r100.xml +BlackBerry9520/5.0.0.973 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/136|http://www.blackberry.net/go/mobile/profiles/uaprof/9520_edge/5.0.0.rdf +Mozilla/5.0 (BlackBerry; U; BlackBerry 9350; en-US) AppleWebKit/534.11 (KHTML, like Gecko) Version/7.0.0.400 Mobile Safari/534.11| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; ar_AR) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0;FBBV/4000.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/2; FBCR/Carrier;FBID/phone;FBLC/ar_AR;FBSF/2.0]| +Opera/9.80 (J2ME/MIDP; Opera Mini/5.1.24009/26.984; U; pl) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.2.1; fr-fr; GT-I9000 Build/FROYO) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)|http://wap.samsungmobile.com/uaprof/GT-i9000.xml +Mozilla/5.0 (Linux; U; Android 2.3.4; es-us; ADR6330VW Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Mozilla/5.0 (Linux; U; Android 3.2.1; es-es; Transformer TF101 Build/HTK75) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13| +Mozilla/5.0 (SymbianOS/9.3; Series60/3.2 NokiaE5-00.2/042.014; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.6.2| +BlackBerry9000/5.0.0.1079 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/152|http://www.blackberry.net/go/mobile/profiles/uaprof/9000/4.6.0.rdf +Opera/9.80 (Android; Opera Mini/5.1.21927/26.984; U; en) Presto/2.8.119 Version/10.54| +Dalvik/1.2.0 (Linux; U; Android 2.2.2; XT800 Build/TITA_M2_17.19.0)| +Mozilla/5.0 (Linux; U; Android 2.3.3; da-dk; Desire_A8181 Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG88/ua-profile.xml +Opera/9.80 (iPad; Opera Mini/6.13548/26.984; U; en) Presto/2.8.119 Version/10.54n/10.54| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_1_3 like Mac OS X; ar) AppleWebKit/528.18 (KHTML, like Gecko) Mobile/7E18 Twitter for iPhone| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.1;FBBV/4010.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.2;FBSS/1; FBCR/AT&T;FBID/phone;FBLC/en_US;FBSF/1.0]| +BlackBerry8300/4.5.0.176 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/100|http://www.blackberry.net/go/mobile/profiles/uaprof/8300/4.2.2.rdf +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/SingTel;FBID/phone;FBLC/en_US;FBSF/2.0]| +Dalvik/1.2.0 (Linux; U; Android 2.2; C510a Build/CN0BB411D7)|http://wap.sonyericsson.com/UAprof/C510aR101.xml +Mozilla/4.0 (compatible; Nokia Podcasting; SymbianOS; Nokia6720c/012.008)| +Opera/9.80 (Android; Opera Mini/5.1.22460/26.984; U; pl) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3;FBSS/2; FBCR/T-MobileUK;FBID/phone;FBLC/en_US;FBSF/2.0]| +Opera/9.80 (Android 2.2; Linux; Opera Tablet/ADR-1110071847; U; es-ES) Presto/2.9.201 Version/11.50| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.3.13337/26.984; U; en) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (BlackBerry; U; BlackBerry 9810; en-US) AppleWebKit/534.11 (KHTML, like Gecko) Version/7.0.0.254 Mobile Safari/534.11| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[9857917895] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (Linux; U; Android 2.3.3; es-us; DROID Pro Build/4.5.1-110-VNS-22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Dalvik/1.2.0 (Linux; U; Android 2.2.2; Nexus S Build/OLYKT_U4_1.15.0)| +Dalvik/1.4.0 (Linux; U; Android 2.3.5; HTC Glacier Build/GRJ90)| +Mozilla/5.0 (Linux; U; Android 2.3.3; en-us; ADR6300 Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.4/26.984; U; en) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/9.80/26.984; U; es) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (BlackBerry; U; BlackBerry 9350; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0.400 Mobile Safari/534.11+| +Mozilla/5.0 (Linux; U; Android 2.3.4; es-us; SPH-D600 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.4; Orange Monte Carlo Build/OAT_B05)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.4; LG Optimus 2X Build/GRJ22)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Opera/9.80 (Android 3.2.2; Linux; Opera Tablet/ADR-1110071847; U; en) Presto/2.9.201 Version/11.50| +Mozilla/5.0 (iPod touch; U; CPU iPhone OS 4_3_4 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPod3,1;FBMD/iPod touch;FBSN/iPhone OS;FBSV/4.3.4;FBSS/1; FBCR/;FBID/phone;FBLC/de_DE;FBSF/1.0]| +Mozilla/5.0 (Linux; U; Android 2.1-update1-v1.0; en-gb; HTC Hero Build/ERE27) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17|http://www.htcmms.com.tw/Android/TMO/Hero/ua-profile.xml +Mozilla/5.0 (BlackBerry; U; BlackBerry 9300; zh-CN) AppleWebKit/534.8+ (KHTML, like Gecko) Version/6.0.0.668 Mobile Safari/534.8+|http://www.blackberry.net/go/mobile/profiles/uaprof/9300_umts/6.0.0.rdf +Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; HTC; Radar; Orange)|http://device.sprintpcs.com/HTC/SPS511BK/latest +SAMSUNG-GT-B3210/1.0 Release/10.19.2009 Browser/NetFront3.5 Profile/MIDP-2.0 Configuration/CLDC-1.1/*MzU4NjI4MDM2OTA2NjA2|http://wap.samsungmobile.com/uaprof/GT-B3210UAProf.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/T-MobileUK;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.2.1; fr-fr; GT-S5660 Build/FROYO) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)| +Mozilla/5.0 (Linux; U; Android 2.1-update1; fr-fr; GT-I5700 Build/ECLAIR) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)|http://wap.samsungmobile.com/uaprof/GT-i5700.xml +NokiaC1-01/2.0 (05.45) Profile/MIDP-2.1 Configuration/CLDC-1.1 Opera/9.60 (J2ME/MIDP;Opera Mini/4.2.13337Mod.by.Iyke./503; U; en)Presto/2.2.0 UNTRUSTED/1.0| +Dalvik/1.2.0 (Linux; U; Android 2.2.1; MB300 Build/FRG83)|http://uaprof.motorola.com/phoneconfig/MotoMB300/profile/MotoMB300.rdf +Mozilla/5.0 (Linux; U; Android 3.2; fr-fr; A501 Build/HTJ85B) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13| +Dalvik/1.2.0 (Linux; U; Android 2.2.1; SHW-M180L Build/FROYO)|http://gsm.lge.com/html/gsm/P990-M3-D2.xml +Nokia6700s/033.014 (SymbianOS/9.3; U; Series60/3.2; Mozilla/5.0; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/525 (KHTML,like Gecko) Safari/525|http://nds1.nds.nokia.com/uaprof/N6700sr100.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; sv_SE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/1; FBCR/TELIA;FBID/phone;FBLC/sv_SE;FBSF/1.0]| +Mozilla/5.0 (Linux; U; Android 2.2; ko-kr; LG-E720 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 MMS/LG-Android-MMS-V1.0/1.2| +Mozilla/5.0 (Linux; U; Android 2.3.4; zh-hk; GT-S5830 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[8648387408] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.17766/26.984; U; en) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.17766/26.984; U; en) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 1.6; en-us; SonyEricssonX10a Build/R2CA016) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1 androidAppVersion/2.1 AndroidWebkitWrapper|http://wap.sonyericsson.com/UAprof/X10aR101.xml +Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Incredible 2 Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Dalvik/1.2.0 (Linux; U; Android 2.2.1; SCH-i909 Build/FROYO)|http://gsm.lge.com/html/gsm/P990-M3-D2.xml +Mozilla/5.0 (Linux; U; Android 2.3.3; fr-fr; Droid Build/FRG83D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (iPod touch; U; CPU iPhone OS 4_2_1 like Mac OS X; es_ES) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPod2,1;FBMD/iPod touch;FBSN/iPhone OS;FBSV/4.2.1;FBSS/1; FBCR/;FBID/phone;FBLC/es_ES;FBSF/1.0]| +BlackBerry9530/5.0.0.191 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/105|http://www.blackberry.net/go/mobile/profiles/uaprof/9530_umts/4.7.0.rdf +BlackBerry8310/4.5.0.176 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/102 UP.Browser/5.0.3.3|http://www.blackberry.net/go/mobile/profiles/uaprof/8310/4.2.2.rdf +BlackBerry8520/5.0.0.1007 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/373|http://www.blackberry.net/go/mobile/profiles/uaprof/8520_80211g/4.6.1.rdf +Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; ca) AppleWebKit/534.8+ (KHTML, like Gecko) Version/6.0.0.668 Mobile Safari/534.8+|http://www.blackberry.net/go/mobile/profiles/uaprof/9800_edge/6.0.0.rdf +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.13555/26.984; U; de) Presto/2.8.119 Version/10.54| +NOKIAN85/UC Browser7.7.1.88/28/351|http://nds1.nds.nokia.com/uaprof/NN85-1r100.xml +Dalvik/1.2.0 (Linux; U; Android 2.2.2; ME860 Build/OLHKT_U4_0.50.0)|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (Linux; U; Android 2.1-update1; nl-be; U20i Build/2.1.1.A.0.6) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)|http://wap.sonyericsson.com/UAprof/U20iR201.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.5; GT-I9100 Build/MIUI 1.8.5)| +Dalvik/1.4.0 (Linux; U; Android 2.3.7; Hero Build/GRH78)|http://www.htcmms.com.tw/Android/TMO/Hero/ua-profile.xml +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[3309904256] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Opera/9.80 (Android; Opera Mini/5.1.22460/26.984; U; es) Presto/2.8.119 Version/10.54| +NokiaE52-1/071.004; Series60/3.2 Profile/MIDP-2.1 Configuration/CLDC-1.1 3gpp-gba|http://nds1.nds.nokia.com/uaprof/NE52-1r100.xml +BlackBerry9630/5.0.0.975 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/236|http://www.blackberry.net/go/mobile/profiles/uaprof/9630/4.7.1.rdf +Mozilla/5.0 (Linux; U; Android 2.2.1; es-es; bq Voltaire Build/MASTER) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://gsm.lge.com/html/gsm/P990-M3-D2.xml +Opera/9.80 (Android 2.3.5; Linux; Opera Mobi/ADR-1110071847; U; en-GB) Presto/2.9.201 Version/11.50| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; it_IT) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.5;FBSS/2; FBCR/VodafoneIT;FBID/phone;FBLC/it_IT;FBSF/2.0]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/2; FBCR/vodafoneUK;FBID/phone;FBLC/en_US;FBSF/2.0]| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.3.26549/26.984; U; es) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (iPod touch; U; CPU iPhone OS 4_1 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.1;FBBV/4010.0;FBDV/iPod4,1;FBMD/iPod touch;FBSN/iPhone OS;FBSV/4.1;FBSS/2; FBCR/;FBID/phone;FBLC/en_US;FBSF/2.0]| +BlackBerry9000/5.0.0.862 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/297|http://www.blackberry.net/go/mobile/profiles/uaprof/9000/4.6.0.rdf +Opera/9.80 (J2ME/MIDP; Opera Mini/4.1.15231/26.984; U; tr) Presto/2.8.119 Version/10.54| +Dalvik/1.4.0 (Linux; U; Android 2.3.5; HTC Sensation Z710e with Beats Audio Build/GRJ90)| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-gb; LG-P970/V10d Build/FRG83G) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 MMS/LG-Android-MMS-V1.0/1.2|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +NokiaE75-1/UC Browser7.9.0.102/28/355/UCWEB|http://nds1.nds.nokia.com/uaprof/NE75-1r100.xml +Mozilla/5.0 (Linux; U; Android 2.2; fr-fr; ViewPad 10s Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (iPad; U; CPU iPhone OS 4_3_5 like Mac OS X; pt_BR) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPad2,2;FBMD/iPad;FBSN/iPhone OS;FBSV/4.3.5;FBSS/1; FBCR/AT| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone4,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/Bell;FBID/phone;FBLC/en_US;FBSF/2.0]| +Dalvik/1.2.0 (Linux; U; Android 2.2.1; Livall Build/MASTER)|http://gsm.lge.com/html/gsm/P990-M3-D2.xml +Mozilla/5.0 (Linux; U; Android 1.6; es-es; SonyEricssonX10a Build/R2CA016) AppleWebKit/528.5 (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1|http://wap.sonyericsson.com/UAprof/X10aR101.xml +Mozilla/5.0 (Linux; U; Android 2.1-update1; en-za; E10i Build/2.1.1.A.0.16) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17|http://wap.sonyericsson.com/UAprof/E10iR201.xml +Mozilla/5.0 (Linux; U; Android 2.3; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.3.4; de-de; SonyEricssonST17i Build/4.0.1.A.0.284) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Mozilla/5.0 (iPad; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPad2,1;FBMD/iPad;FBSN/iPhone OS;FBSV/4.3.3;FBSS/1; FBCR/;FBID/tablet;FBLC/en_US;FBSF/1.0]| +Mozilla/5.0 (Linux; U; Android 2.2.2; fr-fr; LG-P350 Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; NOKIA; Lumia 800)|http://device.sprintpcs.com/HTC/SPS511BK/latest +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone1,2;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.2.1;FBSS/1; FBCR/Telekom.de;FBID/phone;FBLC/de_DE;FBSF/1.0]| +Dalvik/1.4.0 (Linux; U; Android 2.3.5; GT-S5830 Build/GINGERBREAD)| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/2; FBCR/OrangeUK;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[7176681207] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (Linux; U; Android 2.1-update1; es-es; Nvsbl Build/ECLAIR) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17|http://wap1.huawei.com/uaprof/HuaweiU8230v100WCDMAEclair.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.1.12965/26.984; U; en) Presto/2.8.119 Version/10.54| +Dalvik/1.1.0 (Linux; U; Android 2.1-update1; Orange_Boston Build/ERE27)|http://wap1.huawei.com/uaprof/HuaweiU8230v100WCDMAEclair.xml +Dalvik/1.2.0 (Linux; U; Android 2.2.1; GT-T959 Build/FROYO)|http://gsm.lge.com/html/gsm/P990-M3-D2.xml +Mozilla/5.0 (Linux; U; Android 2.2.1; ar-qa; HTC Wildfire Build/FRG83D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/Buzz/ua-profile.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.18975/26.984; U; id) Presto/2.8.119 Version/10.54| +NokiaE66/UC Browser7.9.0.102/28/354/UCWEB|http://nds1.nds.nokia.com/uaprof/NE66-1r100.xml +Dalvik/1.2.0 (Linux; U; Android 2.2.2; G2 Build/FRG83G)|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (iPod touch; U; CPU iPhone OS 5_0 like Mac OS X; it_IT) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPod4,1;FBMD/iPod touch;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/;FBID/phone;FBLC/it_IT;FBSF/2.0]| +Opera/9.80 (Android 3.1; Linux; Opera Tablet/ADR-1110071847; U; en-GB) Presto/2.9.201 Version/11.50|http://wap.samsungmobile.com/uaprof/GT-P7500.xml +Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; U8500 Build/HuaweiU8500) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://gsm.lge.com/html/gsm/P990-M3-D2.xml +Mozilla/5.0 (Linux; U; Android 2.2.1; ar-eg; Milestone Build/SHOLS_U2_05.27.2) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://uaprof.motorola.com/phoneconfig/motoa853/Profile/motoa853.rdf +Dalvik/1.2.0 (Linux; U; Android 2.2.2; U8520 Build/HuaweiU8520)|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +BlackBerry9000/5.0.0.771 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/121|http://www.blackberry.net/go/mobile/profiles/uaprof/9000/4.6.0.rdf +BlackBerry9700/5.0.0.586 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/258|http://www.blackberry.net/go/mobile/profiles/uaprof/9700_umts/5.0.0.rdf +Dalvik/1.4.0 (Linux; U; Android 2.3.7; Incredible S Build/GRI40)| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; ST17i Build/4.0.2.A.0.42)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Opera/9.80 (S60; SymbOS; Opera Mobi/SYB-1107071606; U; hu) Presto/2.8.149 Version/11.10| +Mozilla/5.0 (Linux; U; Android 2.3.3; en-au; LG-P500 Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 MMS/LG-Android-MMS-V1.0/1.2| +Opera/9.80 (Android 2.1-update1; Linux; Opera Mobi/ADR-1110071847; U; pt) Presto/2.9.201 Version/11.50|http://wap1.huawei.com/uaprof/HuaweiU8230v100WCDMAEclair.xml +Mozilla/5.0 (Linux; U; Android 2.2; en-us; Nexus One Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/Three;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.3.4; ar-ae; GT-I9100G Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; he-il) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8J3| +Opera/9.80 (J2ME/MIDP; Opera Mini/5.1.21051/26.984; U; ar) Presto/2.8.119 Version/10.54| +nokiae61i-1/UC Browser7.7.1.88/69/444 UNTRUSTED/1.0|http://nds1.nds.nokia.com/uaprof/NE61i-1r100.xml +Mozilla/5.0 (Linux; U; Android 2.3.5; en-za; GT-N7000 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.2.2; fr-fr; ViewPad7 Build/FRG83G) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; ZTE-C N600+ Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (Linux; U; Android 2.3.3; en-vn; HTC_WildfireS_A510e Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG76/ua-profile.xml +Mozilla/5.0 (Linux; U; Android 2.3.5; ko-kr; SHW-M250K Build/MOG) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; ca-es) AppleWebKit/533.17.9 (KHTML, like Gecko) Mobile/8J2| +Nokia1680c-2b_CMCC/2.0 (06.22) Profile/MIDP-2.1 Configuration/CLDC-1.1|http://nds1.nds.nokia.com/uaprof/N1680c-2r100.xml +Dalvik/1.2.0 (Linux; U; Android 2.2.1; Vodafone 858 Build/Vodafone858C02B619)|http://gsm.lge.com/html/gsm/P990-M3-D2.xml +SAMSUNG-E2210B/E2210BPEIJ1 UP.Browser/6.2.3.3.c.1.101 (GUI) MMP/2.0| +Mozilla/5.0 (iPod touch; U; CPU iPhone OS 4_3_2 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.1;FBBV/4010.0;FBDV/iPod4,1;FBMD/iPod touch;FBSN/iPhone OS;FBSV/4.3.2;FBSS/2; FBCR/;FBID/phone;FBLC/en_US;FBSF/2.0]| +Dalvik/1.2.0 (Linux; U; Android 2.2; Eken M009s Build/Android 2.2 Froyo)| +Dalvik/1.4.0 (Linux; U; Android 2.3; MID8024 Build/GINGERBREAD)| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.18149/26.984; U; ru) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.3.3; sv-se; Desire_A8181 Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG88/ua-profile.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; en-gb) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; Racer Build/FRG83)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +BlackBerry8520/5.0.0.1079 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/132|http://www.blackberry.net/go/mobile/profiles/uaprof/8520_80211g/4.6.1.rdf +Mozilla/5.0 (Linux; U; Android 2.1-update1; en-au; HTC Liberty Build/ERE27) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)| +Mozilla/5.0 (Linux; U; Android 2.3.5; ko-; HUMBLE by Danalo1979 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.16320/26.984; U; it) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.3.4; ja-jp; DROID3 Build/5.5.1_84_D3G-55) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Mozilla/5.0 (Linux; U; Android 2.2.1; en-jp; S31HT Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://gsm.lge.com/html/gsm/P990-M3-D2.xml +Mozilla/5.0 (Linux; U; Android 2.3.3; es-es; HTC ChaCha A810e Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +NOKIAE5-00/UC Browser7.9.0.102/28/355/UCWEB|http://nds1.nds.nokia.com/uaprof/NE5-00r100.xml +Mozilla/4.0 (compatible; MSIE 7.0; Windows Phone OS 7.0; Trident/3.1; IEMobile/7.0; FujitsuToshibaMobileCommun; IS12T; KDDI)| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; X10i Build/3.0.1.G.0.75)|http://wap.sonyericsson.com/UAprof/X10iR101.xml +Dalvik/1.2.0 (Linux; U; Android 2.2.2; msm7227_ffa Build/I700T_P4_11A_FLXX_FT_R_0_01_1010_110527)|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Opera/9.80 (Android 2.3.7; Linux; Opera Tablet/ADR-1110071847; U; en) Presto/2.9.201 Version/11.50| +SAMSUNG-S3600/S3600JVIF2 NetFront/3.4 Profile/MIDP-2.0 Configuration/CLDC-1.1|http://wap.samsungmobile.com/uaprof/S3600.xml +Mozilla/5.0 (Linux; U; Android 2.3.4; zh-tw; HTC HD2 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Dalvik/1.4.0 (Linux; U; Android 2.3.5; Liberty Build/GRI40)| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone4,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/AT| +Opera/9.80 (Android 2.2; Linux; Opera Mobi/ADR-1110071847; U; en-GB) Presto/2.9.201 Version/11.50| +Mozilla/5.0 (Linux; U; Android 2.3.4; de-de; HTC_Sensation_Z710e Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.4; Thunderbolt Build/GRJ22)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.7; Evo Build/GRJ90)| +Dalvik/1.1.0 (Linux; U; Android 2.1-update1-1.0.0; rk2818sdk Build/ECLAIR)| +Mozilla/5.0 (Linux; U; Android 2.3.3; ja-jp; HTC_IncredibleS_S710e Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.21465/26.984; U; id) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; SCH-R730 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Blackberry 9700/5.0.0.1014 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/613|http://www.blackberry.net/go/mobile/profiles/uaprof/9700_umts/5.0.0.rdf +Mozilla/5.0 (iPad; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPad1,1;FBMD/iPad;FBSN/iPhone OS;FBSV/5.0;FBSS/1; FBCR/;FBID/tablet;FBLC/en_US;FBSF/1.0]| +KCI-S1350/ UP.Browser/7.2.7.2.593 (GUI) MMP/2.0| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; LG-P500 Build/GRJ22)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9A5313e Safari/ Sleipnir/1.4.6m| +Dalvik/1.2.0 (Linux; U; Android 2.2.2; A953 Build/MILA2_U6_3.25.0)|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/2; FBCR/bmobile;FBID/phone;FBLC/en_US;FBSF/2.0]| +Opera/9.80 (J2ME/MIDP; Opera Mini/5.22371/26.984; U; en) Presto/2.8.119 Version/10.5454| +Opera/9.80 (J2ME/MIDP; Opera Mini/5.22371/26.984; U; es) Presto/2.8.119 Version/10.5454| +SAMSUNG-SGH-A667/A667UCKH1; Mozilla/5.0 (Profile/MIDP-2.0 Configuration/CLDC-1.1; Opera Mini/att/4.2.20822; U; en-US) Opera 9.50| +Dalvik/1.4.0 (Linux; U; Android 2.3.7; U20i Build/GingerDX Pro)| +Opera/9.80 (J2ME/MIDP; Opera Mini/5.18487/26.984; U; es) Presto/2.8.119 Version/10.5454| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.2;FBSS/1; FBCR/AT&T;FBID/phone;FBLC/en_US;FBSF/1.0]| +Mozilla/5.0 (Linux; U; Android 2.3.6; en-us; SAMSUNG-SGH-I577 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.3.5; de-de; MEDION LIFE P4310 Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Dalvik/1.2.0 (Linux; U; Android 2.2; GT-I5510T Build/FROYO)| +Mozilla/5.0 (jAiLbr0ken; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0_1 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.0.1;FBSS/2; FBCR/AT&T;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0_1 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.0.1;FBSS/1; FBCR/Carrier;FBID/phone;FBLC/en_US;FBSF/1.0]| +BlackBerry9000/5.0.0.314 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/214|http://www.blackberry.net/go/mobile/profiles/uaprof/9000/4.6.0.rdf +Dalvik/1.2.0 (Linux; U; Android 2.2.1; GT-P1000N Build/FROYO)|http://wap.samsungmobile.com/uaprof/GT-P1000.xml +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[9375247748] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (Linux; U; Android 2.3.5; ko-kr; LG-LU6200 Build/GRJ90) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.2.1;FBSS/2; FBCR/vfde;FBID/phone;FBLC/de_DE;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[3095400160] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Blackberry 9700/6.0.0.448 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/121|http://www.blackberry.net/go/mobile/profiles/uaprof/9700_umts/5.0.0.rdf +Dalvik/1.4.0 (Linux; U; Android 2.3.5; GT-I9100 Build/GRJ22)| +MQQBrowser/2.0 (NokiaN8-00;SymbianOS/9.1 Series60/3.0)|http://nds1.nds.nokia.com/uaprof/NN8-00r100-3G.xml +SAMSUNG-GT-B3210/1.0 Release/10.19.2009 Browser/NetFront3.5 Profile/MIDP-2.0 Configuration/CLDC-1.1/*MzU4NjI4MDM0MTc1NDM2|http://wap.samsungmobile.com/uaprof/GT-B3210UAProf.xml +BlackBerry9530/5.0.0.591 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/-1|http://www.blackberry.net/go/mobile/profiles/uaprof/9530_umts/4.7.0.rdf +Dalvik/1.4.0 (Linux; U; Android 2.3.7; HTC Desire CDMA Build/GRI40)|http://uaprof.vtext.com/adr62k/adr62k.xml +Dalvik/1.2.0 (Linux; U; Android 2.2; LG-LU3700 Build/FRF91)| +Dalvik/1.4.0 (Linux; U; Android 2.3.5; DROID2 Build/VZW)| +Blackberry 9700/6.0.0.666 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/107|http://www.blackberry.net/go/mobile/profiles/uaprof/9700_umts/5.0.0.rdf +BlackBerry8520/5.0.0.1067 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/480|http://www.blackberry.net/go/mobile/profiles/uaprof/8520_80211g/4.6.1.rdf +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; ar_AR) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.1;FBSS/1; FBCR/Carrier;FBID/phone;FBLC/ar_AR;FBSF/1.0]| +Mozilla/5.0 (BlackBerry; U; BlackBerry 9670; es) AppleWebKit/534.1 (KHTML, like Gecko) Version/6.0.0.248 Mobile Safari/534.1| +Mozilla/5.0 (Linux; U; Android 2.3.5; en-us; SAMSUNG-SGH-I777 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +BlackBerry9700/5.0.0.979 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/174|http://www.blackberry.net/go/mobile/profiles/uaprof/9700_umts/5.0.0.rdf +Mozilla/5.0 (Linux; U; Android 2.1-update1; es-ec; SonyEricssonE10i-o Build/2.1.1.A.0.6) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17|http://wap.sonyericsson.com/UAprof/E10iR201.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.4; DROID2 Build/STAB)| +Dalvik/1.4.0 (Linux; U; Android 2.3.3; DROID2 GLOBAL Build/4.5.1_57_D2G-38)| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/1; FBCR/vodafoneUK;FBID/phone;FBLC/en_US;FBSF/1.0]| +Dalvik/1.4.0 (Linux; U; Android 2.3.3; R800i Build/3.0.1.A.0.115)| +Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0.424 Mobile Safari/534.11+| +BlackBerry9000/4.6.0.247 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/299|http://www.blackberry.net/go/mobile/profiles/uaprof/9000/4.6.0.rdf +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[6084333669] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.5; BASE Lutea 2 Build/GRJ22)| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[8135033539] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/5.1.22296/26.984; U; es) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/2; FBCR/Carrier;FBID/phone;FBLC/de_DE;FBSF/2.0]| +Mozilla/5.0 (Series40; NokiaC3-01/05.65; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/1.0.2.26.6|http://nds1.nds.nokia.com/uaprof/NokiaC3-00r100.xml +Mozilla/5.0 (Linux; U; Android 2.1-update1; fr-fr; U20i Build/2.0.2.A.0.24) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)|http://wap.sonyericsson.com/UAprof/U20iR201.xml +Mozilla/5.0 (Linux; U; Android 2.3.3; de-li; SonyEricssonLT15iv Build/4.0.A.2.368) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.5;FBSS/2; FBCR/Telstra;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.2; en-us; CFW-MID7024 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Opera/9.80 (iPhone; Opera Mini/6.13548/26.984; U; de) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_1 like Mac OS X; en_GB) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/3.5a;FBBV/3500;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.1;FBSS/2; FBCR/T-MobileUK;FBID/phone;FBLC/en_GB]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/2; FBCR/Telekom.de;FBID/phone;FBLC/de_DE;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[3373773858] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (Linux; U; Android 2.3.5; pl-pl; MB525 Build/GRJ90) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://uaprof.motorola.com/phoneconfig/MotoMB525/profile/MotoMB525.rdf +Blackberry 9800/6.0.0.570 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/600|http://www.blackberry.net/go/mobile/profiles/uaprof/9800_edge/6.0.0.rdf +NokiaC6-01/UC Browser7.9.0.102/50/352/UCWEB|http://nds.nokia.com/uaprof/NC6-01r100.xml +Dalvik/1.2.0 (Linux; U; Android 2.2; ZTE-BLADE Build/OPEN-MARKET-V1.0)|http://www.zte.com.cn/mobile/uaprof/ZTE-BLADE.xml +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[2604424184] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[6092542919] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Opera/9.80 (iPhone; Opera Mini/6.1.15738/26.984; U; en) Presto/2.8.119 Version/10.54.544| +BlackBerry9700/5.0.0.593 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/310|http://www.blackberry.net/go/mobile/profiles/uaprof/9700_umts/5.0.0.rdf +Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/ADR-1110071847; U; fr) Presto/2.9.201 Version/11.50|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.3; CLIQ XT Build/GRH78)| +Mozilla/5.0 (Linux; U; Android 2.1-update1; fr-fr; X10i Build/2.1.A.0.435) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)|http://wap.sonyericsson.com/UAprof/X10iR201.xml +Opera/9.80 (S60; SymbOS; Opera Mobi/SYB-1106291583; U; lt) Presto/2.8.149 Version/11.10| +Mozilla/5.0 (Linux; U; Android 2.1-update1; vi-vn; SonyEricssonU20a Build/2.1.1.A.0.6) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17|http://wap.sonyericsson.com/UAprof/U20aR201.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.13918/26.984; U; en) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.3.5; en-us; LG-LW690 Build/GRJ90-LG-LW690) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[3362891895] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.5; HTC Desire HD Build/MIUI-2.3.5b)|http://uaprof.vtext.com/adr62k/adr62k.xml +SAMSUNG-SGH-A817/A817UCKH1; Mozilla/5.0 (Profile/MIDP-2.0 Configuration/CLDC-1.1; Opera Mini/att/4.2| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[5413311050] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5| +Mozilla/5.0 (Abdullah; U; CPU iPhone OS 4_2_1 like Mac OS X; de-de) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5| +Mozilla/5.0 (Linux; U; Android 2.2; fr-fr; E140 Build/Froyo) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[6142904496] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +LG-GT350/V100 Obigo/WAP2.0 Profile/MIDP-2.1 Configuration/CLDC-1.1 UNTRUSTED/1.0 lg-gt350/UC Browser7.9.0.102/69/352|http://gsm.lge.com/html/gsm/LG-GT350.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; fr_FR) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.5;FBSS/2; FBCR/Rogers;FBID/phone;FBLC/fr_FR;FBSF/2.0]| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.20457/26.984; U; id) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-za; DroniX-0.5 Build/HuaweiU8180) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Nokia6500s-1/2.0 (09.40) Profile/MIDP-2.1 Configuration/CLDC-1.1 nokia6500s-1/UC Browser7.9.0.102/69/350 UNTRUSTED/1.0|http://nds1.nds.nokia.com/uaprof/N6500sr100.xml +Mozilla/5.0 (Kool-Breeze; U; CPU iPhone OS 4_2_6 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8E200 Safari/6533.18.5| +Apple-iPad1C1/901.334| +Mozilla/5.0 (Linux; U; Android 2.1-update1; sv-se; ZTE-BLADE Build/ERE27) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)|http://www.zte.com.cn/mobile/uaprof/ZTE-BLADE.xml +Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; MB860 Build/4.5.91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (iPod touch; U; CPU iPhone OS 4_2_1 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPod2,1;FBMD/iPod touch;FBSN/iPhone OS;FBSV/4.2.1;FBSS/1; FBCR/;FBID/phone;FBLC/en_US;FBSF/1.0]| +Mozilla/5.0 (Linux; U; Android 2.2.2; ar-kw; u8800 Build/HuaweiU8800) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (Linux; U; Android 2.2; fr-be; Slidepad Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; LG-P500 Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.3.3; en-za; HTC HD2 Build/GRI54) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Dalvik/1.1.0 (Linux; U; Android 2.1-update1; MB511 Build/RUTLA_U3_00.53.0)| +Mozilla/5.0 (iPad; U; CPU iPhone OS 4_3_1 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/3.5a;FBBV/3500;FBDV/iPad1,1;FBMD/iPad;FBSN/iPhone OS;FBSV/4.3.1;FBSS/1; FBCR/AT&T;FBID/phone;FBLC/en_US]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3;FBSS/2; FBCR/o2-de;FBID/phone;FBLC/de_DE;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.3.7; es-es; HTC Desire Build/GRK39F) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://uaprof.vtext.com/adr62k/adr62k.xml +Mozilla/5.0 (Linux; U; Android 2.2; es-es; MID1024 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Opera/9.80 (Android 3.1; Linux; Opera Tablet/ADR-1110071847; U; de) Presto/2.9.201 Version/11.50|http://wap.samsungmobile.com/uaprof/GT-P7500.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.4; USCCADR6285US Build/GRJ22)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en-US) AppleWebKit/534.8+ (KHTML, like Gecko) Version/6.0.0.561 Mobile Safari/534.8+|http://www.blackberry.net/go/mobile/profiles/uaprof/9800_edge/6.0.0.rdf +Dalvik/1.5.1 (Linux; U; Android 3.1; streak7 Build/HMJ19)|http://wap.samsungmobile.com/uaprof/GT-P7500.xml +Dalvik/1.2.0 (Linux; U; Android 2.2.1; Inspire HD Build/FRG83D)|http://gsm.lge.com/html/gsm/P990-M3-D2.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.5; HTC Desire Build/GRI40)|http://uaprof.vtext.com/adr62k/adr62k.xml +Mozilla/5.0 (iPad; U; CPU iPhone OS 5_0 like Mac OS X; es_ES) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPad2,1;FBMD/iPad;FBSN/iPhone OS;FBSV/5.0;FBSS/1; FBCR/;FBID/tablet;FBLC/es_ES;FBSF/1.0]| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.23546/26.984; U; ar) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[9034753318] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.5;FBSS/2; FBCR/vodafoneUK;FBID/phone;FBLC/en_US;FBSF/2.0]| +Dalvik/1.2.0 (Linux; U; Android 2.2.2; ViewSonic-V350 Build/FRG83G)|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; ar_AR) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.5;FBSS/2; FBCR/Mobily;FBID/phone;FBLC/ar_AR;FBSF/2.0]| +Blackberry 9780/6.0.0.570 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/123|http://www.blackberry.net/go/mobile/profiles/uaprof/9780/6.0.0.rdf +Dalvik/1.4.0 (Linux; U; Android 2.3.5; HTC Desire Build/cMIUI 1.8.19 A2SD+)|http://uaprof.vtext.com/adr62k/adr62k.xml +Mozilla/5.0 (Linux; U; Android 2.3.4; es-us; DROID BIONIC Build/5.5.1_84_DBN-55) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (SAMSUNG; SAMSUNG-GT-S5333/S5333JPJJ1; U; Bada/1.0; en-us) AppleWebKit/533.1 (KHTML, like Gecko) Dolfin/2.0 Mobile WQVGA SMM-MMS/1.2.0 OPN-B UNTRUSTED/1.0| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3;FBSS/2; FBCR/AT&T;FBID/phone;FBLC/en_US;FBSF/2.0]| +Opera/9.80 (J2ME/MIDP; Opera Mini/5.18264/26.984; U; ab) Presto/2.8.119 Version/10.54| +BlackBerry9300/5.0.0.845 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/134|http://www.blackberry.net/go/mobile/profiles/uaprof/9300_umts/5.0.0.rdf +Mozilla/5.0 (Linux; U; Android 2.3.4; fr-us; pcdadr6350 Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Opera/9.80 (BREW; Opera Mini/5.63/24.1029; U; en) Presto/2.5.25 240X320 Samsung SCH-U660| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.22714/26.984; U; id) Presto/2.8.119 Version/10.54| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; MB525 Build/4.5.1-134_DFP-10)|http://uaprof.motorola.com/phoneconfig/MotoMB525/profile/MotoMB525.rdf +Dalvik/1.4.0 (Linux; U; Android 2.3.7; HTC Tattoo Build/GRI40)|http://www.htcmms.com.tw/Android/Common/Tattoo/ua-profile.xml +Dalvik/1.2.0 (Linux; U; Android 2.2; SN10T1 Build/FRF91)| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/2; FBCR/AT| +NOKIAN73/UC Browser7.9.0.102/28/354/UCWEB|http://nds.nokia.com/uaprof/NN73-1r100.xml +Opera/9.80 J2ME/MIDP; Opera Mini/4.1.15082/26.984; U; es Presto/2.8.119 Version/10.54| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/M1Singapore;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (iPad; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPad2,3;FBMD/iPad;FBSN/iPhone OS;FBSV/5.0;FBSS/1; FBCR/Verizon;FBID/tablet;FBLC/en_US;FBSF/1.0]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.1;FBBV/4010.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/1; FBCR/Telekom.de;FBID/phone;FBLC/de_DE;FBSF/1.0]| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.1.15082/26.984; U; id) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.18975/26.984; U; es) Presto/2.8.119 Version/10.54| +Opera/9.80 (BREW; Opera Mini/5.43/24.1029; U; en) Presto/2.5.25 320X240 LG VN250| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.5;FBSS/2; FBCR/3Ireland;FBID/phone;FBLC/en_US;FBSF/2.0]| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.1.15231/26.984; U; ar) Presto/2.8.119 Version/10.54| +Dalvik/1.2.0 (Linux; U; Android 2.2; Vega Build/FRF91)| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3;FBSS/2; FBCR/etisalat;FBID/phone;FBLC/en_US;FBSF/2.0]| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.14881/26.984; U; ar) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Vodafone/1.0/LG-GS290/V10g Browser/Obigo-Q7.3 MMS/LG-MMS-V1.0/1.2 MediaPlayer/LGPlayer/1.0 Java/ASVM/1.1 Profile/MIDP-2.1 Confication-Type: Browser|http://gsm.lge.com/html/gsm/LG-GS290-NS.xml +Mozilla/5.0 (Linux; U; Android 1.6; en-fr; HTC Tattoo Build/DRC79) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1|http://www.htcmms.com.tw/Android/Common/Tattoo/ua-profile.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone4,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/Sprint;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.2.2; hu-hu; IDEOS S7 Slim Build/FRG83G) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.3.5; es-es; GT-I9100 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.24725/26.984; U; tr) Presto/2.8.119 Version/10.54| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; Optimus 2X Build/MIUIAndroid 1.7.29)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Dalvik/1.2.0 (Linux; U; Android 2.2.2; Karbonn_A1 Build/FRF91)|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.4; OVO Community ROM Build/GRJ22)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Dalvik/1.5.1 (Linux; U; Android 3.1; MZ604 Build/H.6.4-16)|http://wap.samsungmobile.com/uaprof/GT-P7500.xml +Dalvik/1.2.0 (Linux; U; Android 2.2.2; i-mobile i691 Build/FRG83G)|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (iPad; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.1;FBBV/4010.0;FBDV/iPad2,2;FBMD/iPad;FBSN/iPhone OS;FBSV/4.3.3;FBSS/1; FBCR/AT&T;FBID/tablet;FBLC/en_US;FBSF/1.0]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.2.1;FBSS/1; FBCR/AT| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.1.13685/26.984; U; en) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.1-update1; fr-fr; Garmin-Asus A10 Build/ERE27) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17; A10-V5.0.68-userdebug-20101020| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[2605826847] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (iPad; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.1;FBBV/4010.0;FBDV/iPad2,1;FBMD/iPad;FBSN/iPhone OS;FBSV/4.3.3;FBSS/1; FBCR/;FBID/tablet;FBLC/en_US;FBSF/1.0]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.5;FBSS/2; FBCR/Bell;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 3.1; es-es; AT100 Build/HMJ37) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13|http://wap.samsungmobile.com/uaprof/GT-P7500.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/Rogers;FBID/phone;FBLC/en_US;FBSF/2.0]| +Opera/9.80 (Android; Opera Mini/5.1.22460/26.984; U; de) Presto/2.8.119 Version/10.54| +MOT-V3/0E.40.9FR MIB/2.2.1 Profile/MIDP-2.0 Configuration/CLDC-1.0|http://motorola.handango.com/phoneconfig/v3/Profile/v3.rdf +Dalvik/1.4.0 (Linux; U; Android 2.3.5; Nexus One Build/MIUI 1.10.8.0)| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/2; FBCR/O2;FBID/phone;FBLC/en_US;FBSF/2.0]| +Dalvik/1.4.0 (Linux; U; Android 2.3.3; Dell Streak Build/GRI40)| +Dalvik/1.2.0 (Linux; U; Android 2.2.2; IDEOS S7 Build/FRG83G)| +Mozilla/5.0 (BlackBerry; U; BlackBerry 9370; en-US) AppleWebKit/534.11 (KHTML, like Gecko) Version/7.0.0.374 Mobile Safari/534.11| +Dalvik/1.2.0 (Linux; U; Android 2.2; MID7024 Build/FRF91)| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; es_ES) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.5;FBSS/2; FBCR/Telcel;FBID/phone;FBLC/es_ES;FBSF/2.0]| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.18154/26.984; U; es) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/5.20963/26.984; U; tr) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.3.3; ar-eg; HTC Incredible S Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Dalvik/1.4.0 (Linux; U; Android 2.3.5; HTC Desire Build/GINGERVillain-3.1)|http://uaprof.vtext.com/adr62k/adr62k.xml +Mozilla/5.0 (Linux; U; Android 2.2.1; de-at; HTC Wildfire 2.31.163.1 Build/FRG83D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/Buzz/ua-profile.xml +Mozilla/5.0 (Linux; U; Android 2.2.2; es-us; ViewPad7 Build/FRG83G) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[7656678665] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.5;FBSS/2; FBCR/Vodafone.de;FBID/phone;FBLC/de_DE;FBSF/2.0]| +BlackBerry9630/5.0.0.1078 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/126|http://www.blackberry.net/go/mobile/profiles/uaprof/9630/4.7.1.rdf +Opera/9.80 (J2ME/MIDP; Opera Mini/4.3.24214/26.984; U; tr) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[4328893691] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.17605/26.984; U; ar) Presto/2.8.119 Version/10.54| +Dalvik/1.2.0 (Linux; U; Android 2.2.2 AcuraTeam www.htcspain.com; LG-P920 Build/FRG83G)| +NokiaC1-01/2.0 (05.45) Profile/MIDP-2.1 Configuration/CLDC-1.1 nokiac1-01/UC Browser7.0.0.41/70/350 UNTRUSTED/1.0| +Mozilla/5.0 (Linux; U; Android 2.3.5; ko-kr; SGH-T989 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/3.5a;FBBV/3500;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/1; FBCR/OPTUS;FBID/phone;FBLC/en_US]| +Opera/9.80 (Android 3.2.1; Linux; Opera Tablet/ADR-1110071847; U; en-GB) Presto/2.9.201 Version/11.50| +Mozilla/5.0 (Linux; U; Android 2.3.3; en-ie; SonyEricssonLT15i Build/3.0.1.A.0.151) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; MB200 Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://uaprof.motorola.com/phoneconfig/MotoMB300/profile/MotoMB300.rdf +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/CarrierLab;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (iPod; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko)| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.21992/26.984; U; ar) Presto/2.8.119 Version/10.54| +Opera/9.80 (BREW; Opera Mini/5.25/24.1029; U; en) Presto/2.5.25 320X240 Samsung SCH-U750|http://uaprof.vtext.com/sch/u750P/u750P.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.5; ZTE-BLADE Build/GRJ90)|http://www.zte.com.cn/mobile/uaprof/ZTE-BLADE.xml +Opera/9.80 (MTK; Opera Mini/5.1.3086/26.984; U; en) Presto/2.8.119 Version/10.54| +Dalvik/1.4.0 (Linux; U; Android RandomROM 2.3.4; SPH-D700 Build/GINGERBREAD)|http://device.sprintpcs.com/Samsung/SPH-D700/DI07.rdf +Opera/9.80 (J2ME/MIDP; Opera Mini/5.16895/26.984; U; en) Presto/2.8.119 Version/10.54| +Opera/9.80 (S60; SymbOS; Opera Mobi/SYB-1109211775; U; fa) Presto/2.8.149 Version/11.10| +BlackBerry8520/5.0.0.1056 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/134|http://www.blackberry.net/go/mobile/profiles/uaprof/8520_80211g/4.6.1.rdf +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.1;FBBV/4010.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3;FBSS/2; FBCR/vodafoneIE;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.3.3; en-gb; SonyEricssonLT15i Build/3.0.1.A.0.146) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Dalvik/1.2.0 (Linux; U; Android 2.2.2; ALCATEL one touch 890D Build/FRG83G)|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.20457/26.984; U; nl) Presto/2.8.119 Version/10.54| +LG-GT405-Orange/V10e Browser/Teleca-Q7.1 MMS/LG-MMS-V1.0/1.2 MediaPlayer/LGPlayer/1.0 Java/ASVM/1.1 Profile/MIDP-2.1 Configuration/CLDC-1.1|http://gsm.lge.com/html/gsm/GT405-M6-D2.xml +SAMSUNG-GT-S8530/S8530XXKE1 Bada/1.2 AppleWebKit/533.1 Dolfin/2.2 Mobile NexPlayer/3.0 SMM-MMS/1.2.0 profile/MIDP-2.1 configuration/CLDC-1.1 OPN-B|http://wap.samsungmobile.com/uaprof/GT-S8530_3G.rdf +BlackBerry9630/4.2.0.424 Profile/MIDP-2.0 Configuration/CLDC-1.1|http://www.blackberry.net/go/mobile/profiles/uaprof/9630/4.7.1.rdf +Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.1.0.58 Mobile Safari/534.11+| +Mozilla/5.0 (Linux; U; Android 2.3.3; en-us; DROID2 GLOBAL Build/4.5.1_57_D2G-38) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Opera/9.80 (J2ME/MIDP; Opera Mini/5.19390/26.984; U; es) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/5.3521/26.984; U; en) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/5.22282/26.984; U; en) Presto/2.8.119 Version/10.54| +Nokia7610/2.0 (5.0509.0) SymbianOS/7.0s Series60/2.1 Profile/MIDP-2.0 Configuration/CLDC-1.0/UC Browser7.9.0.102/27/352/UCWEB|http://nds1.nds.nokia.com/uaprof/N7610r100.xml +Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; it) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0.296 Mobile Safari/534.11+| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; sv_SE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/3SE;FBID/phone;FBLC/sv_SE;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.3.5; zh-cn; MB525 Build/MIUI) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://uaprof.motorola.com/phoneconfig/MotoMB525/profile/MotoMB525.rdf +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/Mobinil;FBID/phone;FBLC/en_US;FBSF/2.0]| +LG-KE970/V11c Obigo/WAP2.0 MIDP-2.0/CLDC-1.1|http://gsm.lge.com/html/gsm/LG-KE970.xml +Blackberry 9700/5.0.0.743 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/138|http://www.blackberry.net/go/mobile/profiles/uaprof/9700_umts/5.0.0.rdf +Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0.440 Mobile Safari/534.11+| +SAMSUNG-GT-S5260/S5260XXKG2 SHP/VPP/R5 Dolfin/2.0 NexPlayer/3.0 SMM-MMS/1.2.0 profile/MIDP-2.1 configuration/CLDC-1.1 OPN-B|http://wap.samsungmobile.com/uaprof/GT-S5260.rdf +Mozilla/5.0 (Linux; U; Android 2.1-update1; ar-kw; HTC_Wildfire_A3333 Build/ERE27) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17|http://www.htcmms.com.tw/Android/Common/Wildfire/ua-profile.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.3; Android for Telechips M801 Evaluation Board Build/GRI40)| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; ST17i Build/4.0.1.A.0.284)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.5; GT-I9103 Build/GINGERBREAD)| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; sv_SE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/1; FBCR/3SE;FBID/phone;FBLC/sv_SE;FBSF/1.0]| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.1.13907/25.893; U; ar) Presto/2.5.25 Version/10.54| +Dalvik/1.4.0 (Linux; U; Android 2.3.5; ZTE Skate Build/V1.0.0B03)| +NOKIAN76/UC Browser7.9.0.102/28/355/UCWEB|http://nds1.nds.nokia.com/uaprof/NN76-1r100.xml +Opera/9.80 (Android 2.2; Linux; Opera Tablet/ADR-1110071847; U; en) Presto/2.9.201 Version/11.50| +BlackBerry8520/5.0.0.979 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/118|http://www.blackberry.net/go/mobile/profiles/uaprof/8520_80211g/4.6.1.rdf +Mozilla/5.0 (Linux; U; Android 2.3.3; ja-jp; INFOBAR A01 Build/S9081) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_1_2 like Mac OS X; tr-tr) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/Unknown Safari/528.16| +Dalvik/1.4.0 (Linux; U; Android 2.3.7; HTC Desire Build/GINGERVillain-3.2)|http://uaprof.vtext.com/adr62k/adr62k.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.22230/26.984; U; en) Presto/2.8.119 Version/10.54| +Blackberry9300/6.0.0.448 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/604|http://www.blackberry.net/go/mobile/profiles/uaprof/9300_umts/5.0.0.rdf +Mozilla/5.0 (Linux; U; Android 2.3.3; ar-kw; HTC_DesireHD_A9191 Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG88/ua-profile.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.3; SO-01C Build/3.0.1.G.0.75)| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.2.1;FBSS/2; FBCR/o2-de;FBID/phone;FBLC/de_DE;FBSF/2.0]| +NokiaN72/5.0706.4.0.1 Series60/2.8 Profile/MIDP-2.0 Configuration/CLDC-1.1/UC Browser7.8.0.95/27/352|http://nds1.nds.nokia.com/uaprof/NN72r100.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_5 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0;FBBV/4000.0;FBDV/iPhone3,3;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.2.5;FBSS/2; FBCR/Verizon;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_5 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0;FBBV/4000.0;FBDV/iPhone3,3;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.2.5;FBSS/2; FBCR/Verizon;FBID/phone;FBLC/en_US;FBSF/2.0]| +BlackBerry9000/5.0.0.931 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/179|http://www.blackberry.net/go/mobile/profiles/uaprof/9000/4.6.0.rdf +SAMSUNG-SGH-i900/AKHJ1 profile/MIDP-2.0 configuration/CLDC-1.1 Opera 9.5|http://wap.samsungmobile.com/uaprof/SGH-i900.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; sv_SE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.2.1;FBSS/2; FBCR/Telenor;FBID/phone;FBLC/sv_SE;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.2; ko-kr; SMA Build/11002700) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; R800i Build/4.0.1.A.2.14)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Mozilla/5.0 (Linux; U; Android 2.1-update1; pt-pt; Vodafone 845 Build/B226) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17|http://wap1.huawei.com/uaprof/HuaweiU8230v100WCDMAEclair.xml +Mozilla/5.0 (BlackBerry; U; BlackBerry 9930; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0.362 Mobile Safari/534.11+| +Dalvik/1.2.0 (Linux; U; Android 2.2.2; LG-KU5900 Build/FRG83G)|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; G.net A6 Build/FRG83G) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.3; HTC Legend Build/GRI40)|http://www.htcmms.com.tw/Android/Common/Legend/ua-profile.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.5;FBSS/2; FBCR/Carrier;FBID/phone;FBLC/de_DE;FBSF/2.0]| +SAMSUNG-SGH-i900/AKIC1profile/MIDP-2.0 configuration/CLDC-1.1 Opera 9.5|http://wap.samsungmobile.com/uaprof/SGH-i900.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/2; FBCR/AT&T;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.1;FBSS/1; FBCR/vodafoneUK;FBID/phone;FBLC/en_US;FBSF/1.0]| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.8462/26.984; U; en) Presto/2.8.119 Version/10.54| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; SGH-T959V Build/GINGERBREAD)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[0000006695] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Opera/9.80 (Android 2.3.1; Linux; Opera Tablet/ADR-1110071847; U; en) Presto/2.9.201 Version/11.50|http://wap.sonyericsson.com/UAprof/LT15iR301.xml +Mozilla/5.0 (Linux; U; Android 2.3.3; ko-kr; LGC660 Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 MMS/LG-Android-MMS-V1.0/1.2| +Blackberry 9800/6.0.0.546 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/609|http://www.blackberry.net/go/mobile/profiles/uaprof/9800_edge/6.0.0.rdf +Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; HTC Desire Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://uaprof.vtext.com/adr62k/adr62k.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.1; sdkDemo Build/GINGERBREAD)| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[6364393392] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/5.17381/26.984; U; en) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/3.5a;FBBV/3500;FBDV/iPhone4,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/Verizon;FBID/phone;FBLC/en_US]| +HTC_Touch_HD_T8282 Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; PPC)/UC Browser7.6.1.82|http://www.htcmms.com.tw/gen/Blackstone-1.0.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.17492/26.984; U; en) Presto/2.8.119 Version/10.54| +Dalvik/1.4.0 (Linux; U; Android 2.3.5; M9 Build/GRJ90)| +Opera/9.80 (J2ME/MIDP; Opera Mini/5.19693/26.984; U; es) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.2.1; es-es; LG-P500h Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 MMS/LG-Android-MMS-V1.0/1.2|http://gsm.lge.com/html/gsm/P990-M3-D2.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.5; Triumph Build/GRJ22)| +Mozilla/5.0 (Linux; U; Android 2.2.2; zh-cn; LG-P990hN Build/FRG83G) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 MMS/LG-Android-MMS-V1.0/1.2|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Opera/9.80 (BlackBerry; Opera Mini/5.1.22303/26.984; U; en) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.22537/26.984; U; ar) Presto/2.8.119 Version/10.54| +Dalvik/1.1.0 (Linux; U; Android 2.1-update1; MB525 Build/JRDNEM_U3_2.51.2)|http://uaprof.motorola.com/phoneconfig/MotoMB525/profile/MotoMB525.rdf +SAMSUNG-SGH-F480/F48RXFHI2 SHP/VPP/R5 NetFront/3.4 Qtv5.3 SMM-MMS/1.2.0 profile/MIDP-2.0 configuration/CLDC-1.1|http://wap.samsungmobile.com/uaprof/SGH-F480_3G.rdf +Opera/9.80 (J2ME/MIDP; Opera Mini/5.18264/26.984; U; en) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Me so Horney :); U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5| +Mozilla/5.0 (Linux; U; Android 2.2.2; de-de; ViewPad7 Build/FRG83G) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Dalvik/1.4.0 (Linux; U; Android 2.3.5; SCH-I405 Build/GINGERBREAD)| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[3029815674] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (Linux; U; Android 2.3.5; en-us; HTC Inspire 4G Build/GRJ90) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; LG-P509 Build/FRG83G) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0_1 like Mac OS X; en_GB) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/3.5a;FBBV/3500;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.0.1;FBSS/1; FBCR/Carrier;FBID/phone;FBLC/en_GB]| +Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; MK16a Build/4.0.1.A.0.283) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Mozilla/5.0 (Linux; U; Android 3.1; en-gb; GT-P7300 Build/HMJ37) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13|http://wap.samsungmobile.com/uaprof/GT-P7500.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/5.22234/26.984; U; en) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; MB525 Build/3.4.2-107_JDN-9) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)|http://uaprof.motorola.com/phoneconfig/MotoMB525/profile/MotoMB525.rdf +Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; sapphire) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2|http://www.htcmms.com.tw/Android/TMO/Hero/ua-profile.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/5.1.24321/26.984; U; de) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.3.4; en-my; HTC_Sensation_Z710e Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; es) AppleWebKit/534.8+ (KHTML, like Gecko) Version/6.0.0.666 Mobile Safari/534.8+|http://www.blackberry.net/go/mobile/profiles/uaprof/9800_edge/6.0.0.rdf +BlackBerry8520/5.0.0.348 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/212|http://www.blackberry.net/go/mobile/profiles/uaprof/8520_80211g/4.6.1.rdf +Opera/9.80 (J2ME/MIDP; Opera Mini/5.1.22296/26.984; U; ru) Presto/2.8.119 Version/10.54| +Dalvik/1.4.0 (Linux; U; Android 2.3.5; HTC Desire Z Build/MIUI-1.9.30)|http://uaprof.vtext.com/adr62k/adr62k.xml +Mozilla/5.0 (Linux; U; Android 2.3.5; de-de; SAMSUNG GT-I9100/I9100BUKI3F Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +NokiaE75-1/UC Browser7.9.0.102/28/352/UCWEB|http://nds1.nds.nokia.com/uaprof/NE75-1r100.xml +Mozilla/5.0 (iPod touch; U; CPU iPhone OS 4_3_5 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0;FBBV/4000.0;FBDV/iPod4,1;FBMD/iPod touch;FBSN/iPhone OS;FBSV/4.3.5;FBSS/2; FBCR/;FBID/phone;FBLC/de_DE;FBSF/2.0]| +Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaC6-00.1/20.2.041; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/525 (KHTML, like Gecko) BrowserNG/7.2.6.9| +Mozilla/5.0 (Linux; U; Android 2.1-update1; fr-fr; A101IT Build/ECLAIR)AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[5186817755] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0;FBBV/4000.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.5;FBSS/1; FBCR/AT&T;FBID/phone;FBLC/en_US;FBSF/1.0]| +Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en-GB) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0.403 Mobile Safari/534.11+| +Mozilla/5.0 (iPad; U; CPU OS 4_3 like Mac OS X; vi-vn) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8F190 Safari/6533.18.5| +Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; T-Mobile G2 Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 BingWeb/2.0.546.20110811|http://www.htcmms.com.tw/Android/TMO/Hero/ua-profile.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.14912/26.984; U; de) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.5;FBSS/2; FBCR/OPTUS;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.3.7; en-gb; HTC Desire Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://uaprof.vtext.com/adr62k/adr62k.xml +Mozilla/5.0 (Linux; U; Android 2.3.5; fr-ca; Nexus One Build/GRJ22) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +BlackBerry8900/5.0.0.743 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/135|http://www.blackberry.net/go/mobile/profiles/uaprof/8900_80211g/4.6.1.rdf +Opera/9.80 (S60; SymbOS; Opera Mobi/SYB-1109211775; U; es-ES) Presto/2.8.149 Version/11.10| +Mozilla/5.0 (Linux; U; Android 2.2.1; fr-fr; HTC Wildfire Build/FRG83D) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)|http://www.htcmms.com.tw/Android/Common/Buzz/ua-profile.xml +Mozilla/5.0 (Linux; U; Android 2.2; en-us; Comet Build/FRF91) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2 (AdMob-ANDROID-20091123)| +Mozilla/5.0 (SAMSUNG; SAMSUNG-GT-S8530/S8530XXJK2; U; Bada/1.2; pt-pt) AppleWebKit/533.1 (KHTML, like Gecko) Dolfin/2.2 Mobile WVGA SMM-MMS/1.2.0 OPN-B|http://wap.samsungmobile.com/uaprof/GT-S8530_3G.rdf +Mozilla/5.0 (iPod touch; U; CPU iPhone OS 4_3_1 like Mac OS X; de_DE) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/3.5a;FBBV/3500;FBDV/iPod4,1;FBMD/iPod touch;FBSN/iPhone OS;FBSV/4.3.1;FBSS/2; FBCR/;FBID/phone;FBLC/de_DE]| +Dalvik/1.4.0 (Linux; U; Android 2.3.5; GT-I9100 Build/MIUI 1.9.2)| +Opera/9.80 (Android 2.2.2; Linux; Opera Mobi/ADR-1110071847; U; fr-CA) Presto/2.9.201 Version/11.50|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (iPad; U; CPU iPhone OS 4_2_1 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPad1,1;FBMD/iPad;FBSN/iPhone OS;FBSV/4.2.1;FBSS/1; FBCR/;FBID/tablet;FBLC/en_US;FBSF/1.0]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_1 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0;FBBV/4000.0;FBDV/iPhone2,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.1;FBSS/1; FBCR/AT&T;FBID/phone;FBLC/en_US;FBSF/1.0]| +Mozilla/5.0 (Linux; U; Android 2.2.2; de-de; SGH-T499Y Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (Linux; U; Android 2.3.3; es-es; GT-P1000N Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://wap.samsungmobile.com/uaprof/GT-P1000.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/5.21076/26.984; U; en) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/5.1.21051/26.984; U; es) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.3.5; en-us; SCH-I110 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Opera/9.80 (Series 60; Opera Mini/5.1.22395/26.984; U; en) Presto/2.8.119 Version/10.54| +SAMSUNG-GT-B3210/1.0 Release/10.19.2009 Browser/NetFront3.5 Profile/MIDP-2.0 Configuration/CLDC-1.1/*MzU4NjI4MDM0NDY5MzY3|http://wap.samsungmobile.com/uaprof/GT-B3210UAProf.xml +BlackBerry8330/4.3.0 Profile/ MIDP-2.0 Configuration/ CLDC-1.1 VendorID/105|http://www.blackberry.net/go/mobile/profiles/uaprof/8330/4.3.0.rdf +Mozilla/5.0 (Series40; NokiaC3-00/04.60; Profile/MIDP-2.1 Configuration/CLDC-1.1) Gecko/20100401 S40OviBrowser/1.4.0.34.8|http://nds1.nds.nokia.com/uaprof/NokiaC3-00r100.xml +Mozilla/5.0 (Linux; U; Android 2.3.3; es-es; Android for Telechips M801 Evaluation Board Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.3.25172/26.984; U; ar) Presto/2.8.119 Version/10.54| +Mozilla/4.0 (compatible; Nokia Podcasting; SymbianOS; NokiaN96-1/3.00;)| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[3303477870] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Nokia7610/2.0 (7.0642.0) SymbianOS/7.0s Series60/2.1 Profile/MIDP-2.0 Configuration/CLDC-1.0/UC Browser7.9.0.102/27/354/UCWEB|http://nds1.nds.nokia.com/uaprof/N7610r100.xml +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[4175699908] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Opera/9.80 (BlackBerry; Opera Mini/5.1.22265/26.984; U; en) Presto/2.8.119 Version/10.54| +Opera/9.80 (iPhone; Opera Mini/6.1.15738/26.984; U; tr) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Symbian/3; Series60/5.3 NokiaE7-00/111.020.0307; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/533.4 (KHTML, like Gecko) NokiaBrowser/7.4.1.14 Mobile Safari/533.4 3gpp-gba|http://nds1.nds.nokia.com/uaprof/NE7-00r100.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.17605/26.984; U; es) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.2.1; en-ca; X10i Build/FreeX10-beta3_zdzihu) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://wap.sonyericsson.com/UAprof/X10iR101.xml +Mozilla/5.0 (Linux; U; Android 2.3.4; en-us; MB526 Build/4.5.1-134_DFP-38) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Opera/9.80 (Series 60; Opera Mini/5.1.22784/26.984; U; ar) Presto/2.8.119 Version/10.54| +Dalvik/1.4.0 (Linux; U; Android 2.3.7; u8160 Build/GINGERBREAD)| +Dalvik/1.4.0 (Linux; U; Android 2.3.7; Z71 Build/GRJ22)| +Opera/9.80 (Android 2.1-update1; Linux; Opera Mobi/ADR-1110071847; U; fr) Presto/2.9.201 Version/11.50|http://wap1.huawei.com/uaprof/HuaweiU8230v100WCDMAEclair.xml +Nokia6080/2.0 (03.33) Profile/MIDP-2.0 Configuration/CLDC-1.1|http://nds.nokia.com/uaprof/N6080r100.xml +Opera/9.80 (iPhone; Opera Mini/5.19802/26.984; U; en) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.10247/26.984; U; id) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[6144206722] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.22228/26.984; U; es) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.19634/26.984; U; en) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android Eclair; fr-fr Build/ECLAIR) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/OrangeUK;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_5 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,3;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.2.5;FBSS/2; FBCR/Verizon;FBID/phone;FBLC/en_US;FBSF/2.0]| +BlackBerry8520/4.6.1.314 Profile/MIDP-2.0 Configuration/CLDC-1.1 VendorID/614|http://www.blackberry.net/go/mobile/profiles/uaprof/8520_80211g/4.6.1.rdf +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.14613/26.984; U; en) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.3.5; en-gb; San Francisco II Build/OUK_B02) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; Legend Build/GRH55)|http://www.htcmms.com.tw/Android/Common/Legend/ua-profile.xml +Dalvik/1.5.1 (Linux; U; Android 3.1; Optimus 2x Build/HMJ37)|http://wap.samsungmobile.com/uaprof/GT-P7500.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/5.19376/26.984; U; en) Presto/2.8.119 Version/10.54| +Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/ADR-1109081720; U; fr-CA) Presto/2.8.149 Version/11.10|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_8 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,3;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.2.8;FBSS/2; FBCR/Verizon;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.1-update1; en-sa; Desire_A8181 Build/ERE27) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17|http://www.htcmms.com.tw/Android/Common/Bravo/HTC_Desire_A8181.xml +Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Nexus One Build/GRK39F) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Huawei U9120/196 Browser/NetFront/3.5 Profile/MIDP-2.0 Configuration/CLDC-1.1| +Dalvik/1.2.0 (Linux; U; Android 2.2.2; ZTE-U X850 Build/FRF91)|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (SymbianOS/9.3; Series60/3.2 NokiaE52-1/052.003; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/525 (KHTML, like Gecko) Version/3.0 BrowserNG/7.2.6.2|http://nds1.nds.nokia.com/uaprof/NE52-1r100.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/Carrier;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.3.3; zh-cn; R800x Build/3.0.1.E.0.88) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (iPad; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPad2,2;FBMD/iPad;FBSN/iPhone OS;FBSV/5.0;FBSS/1; FBCR/;FBID/tablet;FBLC/en_US;FBSF/1.0]| +Mozilla/5.0 (iPad; U; CPU iPhone OS 4_3_5 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPad2,2;FBMD/iPad;FBSN/iPhone OS;FBSV/4.3.5;FBSS/1; FBCR/Three;FBID/tablet;FBLC/en_US;FBSF/1.0]| +Mozilla/5.0 (BlackBerry; U; BlackBerry 9700; es) AppleWebKit/534.8+ (KHTML, like Gecko) Version/6.0.0.668 Mobile Safari/534.8+|http://www.blackberry.net/go/mobile/profiles/uaprof/9700_umts/6.0.0.rdf +Dalvik/1.4.0 (Linux; U; Android 2.3.5; ADR6300 Build/FRF91)| +Nokia5200/2.0 (07.20) Profile/MIDP-2.0 Configuration/CLDC-1.1 nokia5200/UC Browser7.9.0.102/69/352 UNTRUSTED/1.0|http://nds1.nds.nokia.com/uaprof/N5200r100.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.16402/26.984; U; en) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.2.2; ru-ru; HTC Desire HD Build/FRG83G) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://uaprof.vtext.com/adr62k/adr62k.xml +Mozilla/5.0 (Linux; U; Android 2.3.5; en-us; SCH-I405 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.20464/26.984; U; es) Presto/2.8.119 Version/10.54| +Dalvik/1.4.0 (Linux; U; Android 2.3.5; T3 Build/GRJ22)| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; X8 Build/GRJ22)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Opera/9.80 (iPhone; Opera Mini/5.176/26.984; U; en) Presto/2.8.119 Version/10.54| +Opera/9.80 (iPhone; Opera Mini/5.176/26.984; U; en) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.2.2; en-us; SCH-M828C[9186137710] Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www-ccpp.tcl-ta.com/files/ALCATEL_one_touch_908.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/AT| +Mozilla/5.0 (Linux; U; Android 2.2; en_us; LG-P500h Build/FROYO) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 NetFrontLifeBrowser/2.2 Mobile (Dragonfruit)| +Mozilla/5.0 (Linux; U; Android 2.2.1; en-us) AppleWebKit/534.12 (KHTML, like Gecko) Puffin/1.3.3126S Mobile Safari/534.12|http://gsm.lge.com/html/gsm/P990-M3-D2.xml +Opera/9.80 (Series 60; Opera Mini/5.1.22395/26.984; U; ar) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/fido;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_0 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/5.0;FBSS/2; FBCR/vodafoneUK;FBID/phone;FBLC/en_US;FBSF/2.0]| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.14004/26.984; U; en) Presto/2.8.119 Version/10.54| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.13567/26.984; U; en) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.3.3; en-sa; HTC_ChaCha_A810e Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Mozilla/5.0 (Linux; U; Android 2.3.3; en-us; HTC Sapphire Build/unknown) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/TMO/Hero/ua-profile.xml +Mozilla/5.0 (Linux; U; Android 2.3.3; pl-pl; HTC Wildfire S A510e Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://www.htcmms.com.tw/Android/Common/PG76/ua-profile.xml +Dalvik/1.4.0 (Linux; U; Android 2.3.7; U20i Build/GRJ22)| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.1.13572/26.984; U; fr) Presto/2.8.119 Version/10.54| +Dalvik/1.4.0 (Linux; U; Android 2.3.4; SHW-M180K Build/GINGERBREAD)|http://www.htcmms.com.tw/Android/Common/PG863/ua-profile.xml +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.18154/26.984; U; fr) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (Linux; U; Android 2.3.5; zh-tw; MB525 Build/GRJ90) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1|http://uaprof.motorola.com/phoneconfig/MotoMB525/profile/MotoMB525.rdf +Opera/9.80 (Android 2.3.3; Linux; Opera Mobi/ADR-1110071847; U; sv) Presto/2.9.201 Version/11.50| +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.3;FBSS/2; FBCR/Carrier;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.2; zh-hk; PC36100 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1| +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.24721/26.984; U; en) Presto/2.8.119 Version/10.54| +Dalvik/1.4.0 (Linux; U; Android 2.3.3; SBM006SH Build/S0012)| +NOKIAN95/UC Browser7.9.0.102/28/354/UCWEB|http://nds1.nds.nokia.com/uaprof/NN95-1r100.xml +Blackberry9700/5.0.0.862 Profile/MIDP-2.1 Configuration/CLDC-1.1 VendorID/145|http://www.blackberry.net/go/mobile/profiles/uaprof/9700_umts/5.0.0.rdf +Opera/9.80 (J2ME/MIDP; Opera Mini/4.2.23453/26.984; U; ar) Presto/2.8.119 Version/10.54| +Mozilla/5.0 (BlackBerry; U; BlackBerry 9300; en-GB) AppleWebKit/534.8+ (KHTML, like Gecko) Version/6.0.0.650 Mobile Safari/534.8+|http://www.blackberry.net/go/mobile/profiles/uaprof/9300_umts/6.0.0.rdf +SAMSUNG-SGH-i900Orange/RTIC1 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11)|http://wap.samsungmobile.com/uaprof/SGH-i900.xml +Mozilla/5.0 (Linux; U; Android 2.2; en-gb; HTC_DesireHD-orange-LS Build/FRF91)|http://www.htcmms.com.tw/Android/Common/Bravo/HTC_Desire_A8181.xml +Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.5;FBSS/2; FBCR/OrangeUK;FBID/phone;FBLC/en_US;FBSF/2.0]| +Mozilla/5.0 (Linux; U; Android 2.1-update1; cs-cz; SonyEricssonX10i Build/2.1.B.0.1) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17|http://wap.sonyericsson.com/UAprof/X10iR201.xml +NokiaC2-00/2.0 (03.42) Profile/MIDP-2.1 Configuration/CLDC-1.1| diff --git a/HandsetDetectionAPIKit4/bin/HandsetDetectionAPI.dll b/HandsetDetectionAPIKit4/bin/HandsetDetectionAPI.dll deleted file mode 100644 index 3c50fa44679cac700f1dfa51ac919d8e3d96696f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 206336 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 diff --git a/HandsetDetectionAPIKit4/bin/Ionic.Zip.dll b/HandsetDetectionAPIKit4/bin/Ionic.Zip.dll deleted file mode 100644 index 85e4820f41a0a727367fb0705c7e35be5a2cbda4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 463360 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
  • Qx6IX8N8R~#Xif6aLl!dftM|IBkJ>Jx`1T9Z=b4K;a%1SB;HnF)OGUGX_)@+MywxWzT*U0ZD!JST{0h1RIb;^I*PJ(dB2 zojl7)`)fZ>acC~)Yb2sy7Cdnyy^SUNc7IL-qcy*ku2=1Jd)OtQ*rzl4Y?(Sa5l^_n z4uJ76s(B9+&f{D@n8PpJeb-QQH!5AIQm_5hRiJ_!$!wv@+Ac1 z;4!~43nRs$Z@a072CrtFR$2;V15_p@>P{<1KPlXANO5Bs!^jgeg{2s)x9ovi+VS+H zOZNRgnJ)YdT%TIew#n5RF~`RleQxZ75*Koe{TPuJXL@C_i?DBAFT z2X#v+%+go-dNTwe;*YFof}V9s7MIPAqiBSBAX(%+M(@=A3^nUlifQP+G%Yx3;N=AT z^4uuy`fudztS`vBVAt?b>ZrpG&6s;O>Y10tCWqs`x8;0y=wu}7S)oYyntuOS#cRIX zeGhEdnSI(Bh9f^1PpYwaK6~q_H2@ZtBW0#wG7adPytU>u-w<-}qp0OlbKOgir^LK| zkLiD(Br&(%j!ir#Hi?Myif9}N5X%$u3Sk{+Y*qX=Q8R}k@oq|VOK{Y^OH4Kyk zbJM?Du2_{2GS{{QOT{jDlrMN6v32ad+5N#HdY?tf=i9hGruvH~<+Hh5&0{Oip=`Qc z)(W|w>8$YQPzZY`1D}thx^4?rxq_~kJvrn#NJ2IAgx;%sHj0QH6lC&18?M4{ z5y)InQ#jUEAM!%qlDm6BpNZMHss$G78JF;ie`%e>QC8Lt+OdDT&wTstQx2gH+9?it z%YKb&XK9W?FZ2*ULB`_7ShZL%1;oMiHHI7qpj31I@Gr?ks;&XHN`%YLKX7q>>5y4g zQxRcE?05HD+NNAqqr)PUDstHh=Ckh0SF5%q?MZYx)~k@?5SU!^MxSo!YH13+G&wx< z0uC+Tnv`_h&_4|eJ}t7RwhC~$?J$P!Sn5SareS3f>3JOEHBuH0XW*$;U)p*w;7EsF zVH9_U))h*3;uLQ%UFBLgV;61~b01DFhCOsgpuP>fT`fsG%>~^z1L_>TZTC?Y(S+k6 zOkWC!fL5+x;~*8%uz+f$Gu?p5D-7Q`ry5Au+1NvNS%Muc0&3Y5h$VJvCBT2KJmC8SNQLN0HtC< zpQi0C+x=Dwk5YqKS`MH*Jn4rng|2msD~K6>fv~&7OnY*kJURh?#|vjrMFug z>h7!Dpt~0V2(_thq5)ruEsooLFj$z*2%C4Fq5LCw=Y*QK_Hriqrhe*zZ1pZFtcCKL8e9H)jBS*74I>#>EYNOUWvg9n?A8cqLO{B z_eSE(ifU3b3eg6{ zJrhhl(NY(&2oPokf0cbeL*!ql`W~y)|uJ^&YdE86(Nqc@tKZk8d(|RkKVl8 zO)FPbS`<2~IsR`+y{R9fa9r*uahh9hROa%x2fOdlqy*y#QD!Sp5gar}xJvLO>5Pp< zp|)-OTF>oCId3TwOW{pkhMyq;asXZy*1J0O?W0p1X=0(&jaBAc#M%-JjwQQ2k+h}Uy^PEUvt2iw zMLM^72KA|}SQv+7IsGwt0c-@CDle@`Zjep6#La67m*d~`9lN-^B(C;=B?tChVQdT^ z#OXh{J@M8L=d|J_wTM~Cp}2CSvOMq5i#2XHyZb$Ow}~Z5=`56AS1ihE0y^3=%iHwJ zK-eMN-6O}?uvhA1Kt^jj_bd`UJ$aE@od3pMJ?i} zKJZ8UfiTgKb8n=+6RdsoGCW@%9NLc!Mq}d2=qrtP=Z?p^--xJ{^ND*wp{f+sqnF)I zHaFIz&5p}z05@O!5%PQ(a$o7TVWf_+Vs^H~U6T!eJ=6$`?u_yTt20GCD6t zF=1A!F~l|FO>9P>(wWtFo{%SW&y*DzPmH#_cgO$9SFye4U6kaMowOot0(#k}5cNPG zf3A4!A=}V@$kIpn%mZK{NA3JnvaPefW?~_;d#8LDwz9ybjIe+kI2wJtwQ@*3^e(Qa zQBA0SDYl5% zdi^jym69;bX=A#9Eaw4BI0Ug{F}Ce34P=BN`F&iYbr?DUetYZ@JzaI1ec7 zu!rl||KV(fyVx6C2U^-wonCDq#D3_<=iJl2F_|Y>lThhm# zb>t&BJEygmxKy_L_!uZjYH=vfP!M+<$OpM_6`{aN6>c>`Y+9BTsAbr##Um{ z&P<==i0)^Co>dGvUkMID+QeK=GGEiWU)npHmhz=QOz$Ru;p<%T5h+(^Co}|;1$TrM z)_1M@jh0q7?G(wh2spr6b)!B7$3vg~JH!0zYgchF(;IxH`k@DSAYEEWzN*dJ2%Z|4 z^cgwQEIK)55C>f|6UF{KZWL5d^&xt4g9D*V`_VBpjkuzZ9l?RApO+gP4RPp<7NAc3Tsl6!ty4xk5 zjvZxPAeLZjpqCM0o1 zHH{Xl!PUrh*N;;z+1H0?$yP_)ca%Xw0>FEenwb( zQ~w_v1{%sd&FpNa8lpB_U%wA5n-@J_ZuZ=Gjcu8rcWu}eM4IJ1EDl>7I`V{Z|Hi$e z+PI^=@L@3h)@+UttCg;l{41$!#1n~j-?MQbw*S@N1DBQPBkn0OFO+fFj)>^%e z#4hVj3E@%HB6A`v;v%YWYDcd{;vhI1u@V-fKIM$BoBl ze4O1u^8*$wmhPuJkAkPurOm)w!3x@+B@&0PA7UiWcL!sKz(Q#Cf`5OrDmgE=uPLH< zp8o4hP6tR83|di1p9Wk8NCb0eI~SfGFlpW|{g%j^YBvF^XiI#Yo15I#lKAkBk0wzH zrTX&EoVE!=KQaw+R%DsZ7ELCnnZCgvANk*1KR5?rX9LZ<0DX^j0HcPzRgWwBZ3HgCmJ z&T?C1zhqca-+_B(A;OjbHKb?*OOjugIxc(lOUxu{QG2uK-g%fT?XDj`2u3VYn5W(n#+v&-xlx<>`sTd9^d)e+MRmzh;Wc8i2F0hdS1|rKUk{4- zO4>8pasN<8V{4;(?%pp^F9&}iPw0+jxq>~t+OY`a^l^4QCj4RYIP3sKkqr*jKikJ$yJUJ z-e(RBEgy-oYDeWd1@U-o1qgsDC8mGeJ6R=e$1x%opDIIaN%4*1J|mL%#9M)vQ>Vkq zw|sl?)G%tIKO;UQ;h!J)kh=3Bj&};*jcw@%(B|N@M(1gx&MV!pCxys%{c(Gq$7B9` z;xOK5rKStqzRg#_-;k*eobsr4g>@I(zhtgeucR%L1Mh2qxsBUjPi&P~eyuK)E(Vp|>fjQixl5`BGUs+Ebra2nHNc>JMr2ZTJjqq0^3a&0C?qL` z`U`bEd)#mg&fr?zOc%^XnoP}^yl2s*p#3k5M^20qL3ux_gVPXtiOAW2gU)#++j<`g zT|wHW;*G+Z9u5bxA(Odl;@tE%6R-I_`8G{1DR7S*=#0K>2au1`?==_aumq8wq7+5w`Y+`vLnxRAuSaa466G$N!HUbp>vvhgq7g?v;bx>z6nI!j zUU(r7URriK6rF|39kFt~%m94VOH**b^8v?oD@k(k;&g-K^*r3<`gyC{zm{rHXY;D> zObu>plu`??OP|3k?y>qHDnOr{J-cwU+cQHGEz54dAqib1k}tAv)-P-lxc)AE_#T1Z zj>D_}I_wWyrhXrUFumN`rsrt>kh|v}H^0v3h}a6vN(24Umge6xL%I9eVWoH>^(Lzx z8%wdMQa`BBG;ZO7lVfy?h{O+jihWkVdk$7`zGA`Kog4`VeP-Y(T!#tG}WSc~rdI;*+`)3Fh+xXuS1aRBQ!Ev%aUUP&~mlhqNce zHan{##4L*t1KFW{G#wN3<#!SktMPRkb)o)~>ZVKHz{@m_+tO?&&nKZ6$Bo}zEdbtG zZ<=|l$WP*o7S9SthHC`;hs3B-5zK$nlYW)Yhbi=tNuiSEnI+5Jwf!5RzveM|H9oUt zF!eKhq=`^DXQhbPs6GYzPzR9B2xltOO&{MGd!5$=a;Is~_LD5S_!Dy&##cVaqQajr zMi#?(T~w#u!hNr`~Dr_qiX-{#jUpWs>^ zS{wT~p06t@wsTG^^VR+eMZ|91(V#IWrMnts(x6rS;`1L^Y}j0K$2N+?lCigKLUh}o z0T44Ec!c-LnxBZO72cyUyZ);NT#I>~9Os<*j4Ty2#zNquSDx5EbZIxA@xX~N7;+a# zp~tBVU+63pt*(U!QwK%rK1 zw*{5<0>HI;XnV6LuPv-oro6~h1>RKQUQdZ<%pD%RW_&G_=W)~1N%Zem5V!tNW*Tt9 zOP~p(Ch2I&3yyxa#wn*cT21Gs8b3EzO}VH+d9*2N~cr6kNrIh-UECk3J7aT0wGkzZ=5p(UV7BenrROl z^~}N+GJROpa|0x7@nW4?<33fsePz+qC(Q1ig~RBDyVjo8*rw>){#v=uFily1vvj~c zRtKKTPDLu=xOE8x!RY%2dHHwQ2d?N*`6Z-^Vzc8CYw_T12gZoDcA(uz(st^{REd7Y zdA`y?Riif@iV>@lRkSnu{5JR0QSk4KwU1^vad4BLp!ucHU4?80=H>y%N3NL0&`i$oIthu~Dwy}oX8!l=oD%Ov?! zgz0(aOsujQO?FaV%0jE9N&~PSEKJ+GXzK4DZ`C>kqd9{&Av}437oRdRO~%g>B<9ve zQTn|y?i1vcKMe9BIw*Zd$6n7NYy#|z`UZs z0xpM?R*(6y!B|Ne1JbqtrI;r;6sQ;CPhL26{BQ9z*c&Xhm!Fk_>F9b1f?jAF)`=f{ zR0m~m3x3lyhkEj;+c_XA@TZ-^S{qD@OnI<6(m4OEvv@I32wQ7jCU6=Aq_P)&rmR|3 zrC&mhkR7xriHV7mHBzSQ#|R=a7Azz!OBI(~KVgX#$hs4|LFBu4*F-D(uK;+`$(i`| z&N@Y-Zn#?$!ujx>r7tn_TbT~4a9F2TJjzMKW_#1ZjnP{DUu69=#lFJo-_f?o$=I4@ zuc-$3-V^QcEA*55k$I=~fPhI~aSLpv13OMDk5pLXa6co4imL5K!BDrD7F=jEFQB*I;9Zjo&FmcW(iumMxqUPvPqRt`IaorD= zm^jz@jonkRiiYJj+jPQ0H{AIfSaZCgc{aUQgc!5&I@!OfE@$#tH2VNB_pOSsfaI$) z8XajH$|5%IXpYN;h3Az={;+P(WqB$uLzpV81Cf6Y@DU zHA)=_avM&}*SWJSw8uul&}$T=2-*U;>P7uMMQESWUug^^AucFA$s4M!$Bhid1Oz7d z7mqHycaqI9e+(JE?R`)fTw%gOFcgTEM|{|}S2Wg$^Zv!^t&e_I7G+BQgz5p^!lM28 zS0EZ|u)iu0pL4SZ?mUwo6xcWhBR?unnegZ{P@c#4O&Br(n!iaV50iL;HjF6xm?kLi ziNx3ioPFeBw0$Cf^+#C{!|$u6+@taKGm;n)!wP#MM&7 zqj4Mn1#MQ_fVbRQl$!}kD#kMZ!PAdelEvwGXGTAI(0ypCw1l#sX|hQ^+Z@ST0BcWu z$y#89hvCh9oY!#T4245;2`3+woS$^E?}+)yoxZzK(q{zn&%NSB5&6@fg!~XaZ4*(0 zuFfe${X=<}JqfWBVp;!i;2rKX+k35t$ z=?xPN&NpRpWu^mf!`sQCn93XZc*R0ZDDHZ)n@ZUl@`; zm`l|Cd#JQ8vMat6`-iTtQ(&uI!48zd4c~MFQ)&?pj4!zYvi;ou{|3=2Cw@A|2Ce6a2Ah2Ou|PSaSR zFVvvpn{@2l{QaUF(%ceb+x0j^2Ezy%CLNE?m?nGM8`$nfo&faZnQx#b(nzn3BRT)W zBCE(YB~J~3CNgQd_D1}l1IyJ%$P?Qn@Zm@XrIHqHjXg|(qz#S|`w?HEfifL8#_~0V zKT%mqha@9u(Kj)2v`g~XiqJ#oWFu$`j#|C%MLiqhrFR5X5GH8R5G$D6W&pBcXi~eV z7%Vh}x6CA^e25~LVRuKrE*0z^1O^6ZljV;482!j8O!K2(e*I1Ns$4_Gkqn;S1KJq+ zv{6E9sv@$7=r=4g--LAnXeCz}gp`gJyCp1bM@E^VoH8bf7=Irs5n}8c`oCTZ`QKS# z9O{o(R9=U{87;98V=*#0j88LGG_*gzJI*OeUflp;UCajndIwY*FAQ5!Jt5myeV@(Q zu36|7o&9EBjlTy8BcM}C6a6$krOyl{mZmd6l+iL&uPyqO-G+LN*#Nm zIFooq4Z#^#y4T0bGp{=P6JsTYay%z(SwixHu&ea3x~mlFHTi>-p&22Vm9V}W(E#8- zZ}4L^dO8RjhQxXq86x44;d87sS#!Faf{!A!>^LI)KiJJJAt_DAt;q*wJvA@o1wlT| z75o}p@Y^053NuFovl~O%`#ayQTKS^2U0U5Px`&W2@U(w>jYAaZm4} zq4+eu-tAgpHKnXfNJW@$8WY{-uoUNTBYz)-D1sSSuK1k&D*aI zvN0udfPCCT&*ZKwgSRGZR@J18T~4^1GhIHNxt|_{<-SzmedX8XeS%T`BfF>8Y{Sbe zv5$PZ<+{e2E6lo@Bj_F6#!7O4A-Ol35mTq?tMVOd5N8M~%cH6Yw&hrMw36|j{*82s~d^uUfz z6U`A?gMqe!0mX6{Q(s~`3L7mMIR{|R>Dj21ATZ(FZqh z3l0uDzS>&HyU4WZ*qIgkpIl8TR`1aeh#Ft_7p}fdhlZpXh_Zf_S><#3b!b)Nk@VkA zy7YXzDlq!3JgD*jDk0u6T-W~FaOh}IHfE$%zO_L4#t(Nrbu=OnABP($tSMUx?c@UK zE_5H653cXA+6y}He$aXw+!`hETmbAY3cOt1=J(j$9EK_RBo`#oFJC#Vw?)Nx#%CO| zV*GzYN2Wc&-G{lwG3!c~7M#{*+(?muzXa!QX9IU?{G};f0uSOW?r13VepG2a|+s!QZ4xX!>>-S2QsvqXQXS z$~cYiHYIISH|qQ^39Q|vVXU4x1`TNYBRJ;-VRJZc7>*wAJtFc|eyBjX`t^HJ*keWd}gMpD!N zE~E+QgjY!T5cgPbzEOPz>ib#O5{OuZ`*VQr^fG58ZVrzA8dg+m_Z=?>oG-h!J0nT2 zXT?cyr&kG$1AQ8{qTU$WNO=^wztt$R-dq1*RqJ*zCuNj2KVxzqZ)0&ULQ3OiO+I(~D0P?***IAha^RfgIKz*8ZLVPWNg3IU+t48L zn~)7|`t548@3Rq)QDEy;3NPG8(VLKtDBQQ#1%VJ}giF-NJ`=xZ5OF4}Gr|P{tj~LP z%>2=cnXINT-{;pLNBbDXHHCKfn+EB=stcFDM4+Cpr&;YDJa|YwY&53@Zq zJjLXv7ZQ21=xj6weC7)97IJ=h-tW2yoj*zbMcjxi^hctR&lnhvIn7c@ICz(3bxg<0SNW^om;#t`gM>70+V|YulxBv8nu%9aIF| zL}E1YgkOyWuvg*t_|MgU*yV01Q|5UydA8iLlz+9y;My^~Q^b{G*5R%xI@WdEgW4-q z=M^-k_(68fv=ixeLzyGJn6m;1u^DCRD?1Wyo%gHPg> zLt^?de3*PuE6O_0%o@iR2Joahu+coFKl71qI0=w*ZlK(Z2V07Fi(YRFjQa>GtLJJN z!T}x?uDo7f=R;-1;P3Rl)W)Id$YcdGuEUY{mx~{gWa9JeG+dk^Jg&Yg5>LRcwfW%+ zC5wgpgNlbVA>^_Fj@6pnt&4FtO<3b~S>fN+07=CqE|qRt)64TQ`S^m<=${$Xz&g)o z24{B62T@@~w9hlWbMM!ljF&r&6FK3ZTl!|n&O}GF=gB})_Q}lm8z_g~Jz|&XOPYP> z;G(}|A-KPw2+Tziknb!DaB567l9_CTaTtuu93iIPx%d0m= zSB1mhn5Po)pDA;^{n6U==qVLKBNmbCR)nXBZ?oW7N$tT@dBc$6(y^X4kwYi0giA4N z^r3a&#kIfkl?Y@Tv5dUg|0wy{_{KU%U3bf^29EWcQlE4PUl<=X;%>oj$7Q`bDS4u{ zjnO&wxkp+^?VIp<_9oR5BUmKXV?yTL{p3=hj3nkX@7&&14FK%To2k62t-IycpbeBoYRkmk&aj)%WLm6zx(t!xK( z))v3J8OQit%_S%o60D^Uh4()8u;{mWCVC|M<x5Aoz!|)O|Ecm4S7(?U!9&<;`JIAr3(0)GT5#ce9J zV?woJM$%q(+eIj5%&^Jp7_p;b1$-6Kr~&HuuGitMaT5WP%{i}}@k`wApS7B-B2PjK zHCh?60-GKLQbrvDW~-_=4Wat;>}IB`+vf9)6D}i6Ow{A!51n1kJ)!6GzsD5Qq-95m zFS3Un{+be>bvO}b&)Rx7?;*>u#;)+%>e8xydR#r3oXS2S5a{3NTP4G zh3?%pe>?Ra)s(PxP3QJ%;bk!{2M_d4N=e(H7_-F_DEQa!2QOI&b3*5uz5piNNaH$! za2i5h>~Rl%l5M_y`zG-MhWfr+s&h{na%WC=T%v!RTYhdy3KPh8LzU2r1aPLcPDY= zXeyuA?=hc!N502G^>tv7I%4Yq^eeJq=t*kDv|PJRk;F<)e-6f3Ae3)0a^L8w&mSN>2K@@IY+{($DJ|R5!NyGi`qMza+f#3TGLWdQ0 z;_9DHQRM*Y=zTHptV8$8-MDrq8_yezdk{$P74I9T_=9fJ;^_!!$Mt$4;)-|gjtFJq zTdG+}^VX79G&x$E`ZT@1w9tOI=t%SS8O!_0^~4pjos`0{vY4quT6+&qm8GZFVRkYt zpARr$shnGTBJDG8I^If4o4nXIVpd-JdQ)<*x_E;ngv-SCV+>^!1wIvK)7hi3=lC<3 zpLf1Esb?^p({Sn9vDWI)W9U4Dw#PfPKU0W&eMDEqqpUP1{sK_P{RZA%fU|RqlH)MP zgI>YK$a%Bvbvn9svZy}6w5pY7A=M88(-<)yHD1WX;NK&8N`KtQr;1`j*;?(;v%3lQ zVUiVSrwB%l#<56++|oVL%FN(m!25>IPU(eTzRkolM%{9^-O=K~Z1&fsbvumKO&fg! zyA(MCt7j`{XsX9(qfTBvl&w_mWd9{(!+msK^;+lgO+H>@N@l{d7A+cm{3IKR$2N&C zYWBgH5AQw2amke;X1&;6s(}t@;31;r3(hn zIOFn7s)vU#)UUtSTM<88xT=@-JWjFh(~K>xbbcFM-`nY~DJsM~e#CR@N%NQgO+RNq^%sje;BD)zn80Gd~jS_#QKdq*rhUd1GFS>h?AA69`T)%L81bqRuXy;Z4RP(M$ zTwQ;a_w?3b4#ml(ET)X|PKxK=j@VDH!SVW0mr2o(N8P3A<-H9FT&3gIo{Mp5*?9A8 zbT0fSIw|n);g{WQWf2!o2oBiWJo7H*(L+9qk4Z!9ZW$ZBH=o~5(q5Y(A7!Dhm6?=` zx%7to+4|zA`qP_yvtM(14__btbU&ZiV+l`&Lg!puSDSKbrbb$R;kcP{mB7piqEBLF zX7zP#8Lvssm=ja>FU|=wn{&Bw&F@xi4~Q4)#Az+HL|0Kf_g!;@%ao|-t&cH@igbKQ z=52zV9o;j=$G(xVrS^o7P^ggS5`ei2xxA+tMbgEzB| z&J|QUl_Mlf?B`$Y)rj}3tg=Z;JQSQ@Ej-Mu`@kR80vsBAz{~yYgKc$J}HUy{6pT3VTvn`^umVEvM~xo~-?zRBo7k?P(~-s*Nk=u2SQh&SMj??!oOf}X2v zto-V6(pNct{sk61O2==C(1sWWRaavqh+bmTSvG+awk!#@Vb7byw>NId$OWF2Az9^i z_cTyq@PB?b(Qc=@;WkfHLm-uV+R{1P`p>J^eTgrg6Psc_J0u&M875LiPJ}U)-(LfN z9=fgENg{N&r+9N_p7mAZZrebj8TCloWvcX??$v8jF)%7!g(ih#P)Tnxd}N_|BeHn; zTS{J>drp6%w^0J_Xu|n{z<8E`#Kb#~V^5xlKCdmxH^=s*qNU@7^v3BbiOA1{?5N6g zA+2n_eqUb9z=-rB5rAa(VzHrR;-U$NlBkk90Xy&wnQjO*FDr!0!;MQ7{jxM9n*q>cJB!c6^&FHQ( zvk^{o376H+oY8aBQ6W${5?(M&pMH!dX7?XfL`O#@1nCZYBY{1DUWGhk|- zWAlr;iPqH3NHoPo1rjWscT-BML&Y@hqXps&H_$rBPY&J+i6_b{S-ljJpSko!6cs`t zS=eG)U+dPdwNo`}vKeHUGQp;wBC!)8Bfi-xymx!O{|QEnBW+#S#IZ0R^?O&`nqJUo zpbi&(Riv{Pv6yAWeIgpd%XA61NZ0r^B}+tr@fnGY2N&LVx6-o4)1c@%6J9-EF+G=i zcjc3$IVqT46ll6L^YAV+XE6(bnaxbpE3*VR&}Rseq`B!xBPMy{-=l4ziZ$nIkbf8- z$>LD9Tcs3FHJlKjd427(&xhhU_H|l%!{~c<=jtBQ-{5=~HboP_=_<`;**3>>=qQgq z^|beBBL9iR?}qZRAIshA)&0CR!xoyv z(akHU*2Bx6;A6%&I>*kNvD`LEXa)<(5M(E=-@sa|jQnPm!zD==fm!i-r!PYSVC*?o zX|RE9`rX0WYv<-LV{|r)couxSx-eQruL-%nbVePGQloUak#9oyBLAqxW0Gf)d@rM1 z=cV{;blW>fX)0;0Lj=y!@XRpJ9I}X#P9d@#%3C*Gh;Q{8pz%mo)~On}ftIxGu+8tr zfD0YTBr=EW6N`lm-u1{ZYF9h3HDI!aS2BP$okNy4fNQmhlPne2hZEGsyjaoYZ~T^! zMyR6Z_7R)5r6(D$Cn=&zyYuhK7uAGgj#!Vn^B;TEO7s*KnUp8!(uLeQ-u3zVX9Hg0GiiKOkN7cbrH{*?{XIn zE$&R|wxdpm_yyd`O|GN$uk;hVGLcnRU)(CM zLUT?{*znPB$hta;Poe(2TuW(s1M?}9G^Mqk(^HuS?V0|q7909RbrQ2fGJS19V?kfr zE`1zVCwf|7D8Klb`3d!a-N1HuLStdr&6VSo$n9c~+nwP(r6(Wpkp1wpe)y?G|85g0 zMoE*@b#>Ltx3hM-KXB>jvR~NZCy}ux`hW0G@|hig?PFH;Kqdzp4IU5p9`h#iys^9t zUo${@0|_1eP7HFGQ|~wb`_KPs;D0snzZ&?H1_Zd+(bZi7&^7B9N%ZRHRCVj-%Czei zR!wTB7i_=umTE@ly@j35LplTLIHbdnFd_XvJ@gtD2~_jiRizvQn=}*3HdM-|fL7x? z(CJtOx;<+^w{a1;_b&j8qPA)XlnoLqBxHKL2CcvbL-~$1k2`y3Df2!VA8$=Y0su}1z7j20xO8eYGeag4sQSpNam2tAb!1=LJ;p^1?+=j!TaPo zpxyEf7!9lgLr4gI+176$_)9SW;c_6jsR=kYj01@C?sr0DxCQANBw|Rokp3eXJipFy z`gANtd$cbOySFdxx^}Ms=e{-IIJ6ENMmK@|*e0-rtqmmWkO{qz5@yIBLqJ)BxILB z00{%qzjgR_EVQ9|S3%(525^V^beq@$E|8odIgM`t$MH?z0P!O-*!`6p5WiMZIS5Y8 z0nuS0;A3qs&~IA+#)Iqoqy_Q6g!p~BM!@v^6!0HiIlzB_8}T0mJ0m1oNXY#3Z~IYD z&kFFH*#@4&JHUN%YoFX;>k8?2IX3s@_$wI@Uvf*$2PL7Nz}YVZJkhlUS~X+91nR>C z%AgJLOE%5|zu{%Dx3>rUAb!`TNksoY*i!+rYVh2Y60F zIi|LN2P8z6Kg#fnEub$UK4lI4$RM);q&0Sfv``d?i;oBTjnn(%0vX%d4ZrE%AL2(2 zzY&PPc^^NbZv;2u_Xuue3{ycu@RLA7{0Ny_|EVv9_N{`T@A$nTey?dnhV36R?AzkN zrw;rH`qY6fY!Li01;EqO6F3D&1FeECVEA?M$Jo|^_+K@B1O6kw;Ya+(tz`<)KjJG0 zZp7y=K%#(ju)dv!uaPwlnO6}zATs>rm=1^dgCTwwsDB@b9U*T>zsUjZ0B!MSfBM}P zcB31>Bc}qCmz99n@L-^;qX%?rMt{stx)A?sh(8eO9Xa;#w@xGY5!?s*{u%cP_&y<| zqmb|*AvVB*^q2S}`&U8ew;kXL@uT24K*$Hu?=t+^7C(<|dx&2rwHD4n72so#FNm%0 z1Ez4kJ(y?p;QIRp&Zj}&@du5q0Qa_i{D_|%;64Rk|B4%#M-km4*#Dvaqagk;1pmMe z9LJELEf5)e5jhTQao|sXVGBn%C;24hfQ(Qd;2#wSBwV6_0mOSS&+0?`a;H$C z`G17_H}q&|u@Hac{BQUJA$Ej*li|;{_(x;gI;9lE#zX<9uvlQ(2={6|>p#{CqoyUG z(K!#ydzOI1&=NpF|MBS9$B+2;{}}fH{iYoqL7OnN z2BH^s_x&dXVn=9S2H5^?i|s$i@$1;uEBFfHYQBQ7kO1IX&;U%@miE^>&q=t~fMeMh z%3ufgB))y~z^P$K3iAG!$V^fA*)}$A#zQHgNjf4HA=+04h8hD93yOx(#rR z{l5S3fNd0<%iwbl@a|jquj5Y}Spx|O{-GTZ1#w3~Tl|m#o*&5Yvp?7`Z0zUnV|8@N75P#zG-ah_lh#jGQ z8DP6_hkY5o`xC_Rvn^25JHR>P6L2*(0A^Y$z}*g(E(|pTv-fX-+vxiK9?A#euUgp! z<`BQ{z|wymf5vzGUPHSeW^oV1KwEr-^g|Aa|93flAKQUY|JF^@Aj(1=JYc^K9zA{v z-0f|_U}ZW`lz0g7ukP=mf@Zcr&BO zVG9JmP3<7CmU{ut(Xs&J^jZ)T9theCqky!?ec&;+w!eppfb&-!)V~$PkAi#XzdK%k z?Vk-c2ev@wC%8WNG!25!vA)2fQx z3HqyZL1S(dC6 z2<}AqI^j<;?EN+-ei;`&bwK=%2>$W^KK^`&KVuaDUt}JKc#|RipJn*7Eq?bW z&*?qT_BjKLb=HB7no`hFnG2@dD#2YIez+Ik0zuGsvY^e{A%3U!We_m2{$JOB!B6;; zpd2ZX4rKUQ4rE*$j0t3%Ben>h+Xa|v7KC14JJEl!R*8+ zSe_XHTN8tT=aCpd_TtDMs$p#xOm6Q1w~l2HIQ8GhUj%KMh2S6A-Pb*W|3HSHZGp(} zLym(n0o&lOLtvmP8>}xcz^B7a02ZeK{|nju`4!niHLm}L-@Oy!hhzFz{r%nZPv7yQ zAbtdQ+IRXZ8GiLA#1{T=PV6pC0LybzU}bp`?97Y@A16>ey9(g)wSOS^ zQSkXO7|Qf__5ExAf2RK*cK8c_LdJFq#GkXg3s%Q^L32YbP?UZS5`x@8QA{xCo?8Ze zTL3ge|0#z1AAg8H1kOjl^8dT%{|^2ia{S^?c~Gt*I6ezjcEDI~J21602H`2t4uLTs z1jb6D;InTy%prup7+LTLZ0C1;|1REN`~Qp|8M6mikv8KyWqxmw_x8s&)O{LUzfu== zKni>|OrC-`smixoUH}gU#w`@bEx4Abi(XBPD19Jp7^o7(~fGn=3Yu9e8zmOHhvmNB(Cm^!^xnmn_GN|@Oe z3tim%KcdTj0rf9G&YamSMPz_Dm$Ife+tX*Z5>sclOq0HC-}}oB|NG{DO#{Ep&S+@= zx*bF_gEJoh=4j+dy8)9sNLvDv&amBqh|pmRPxo7M*rLJn{nqSz%k{m5p11%0ukFF- z-}@o=MXp2mAT8JT7W~%Y{QtZq_zfR~iQq*?Gz{B)MI(Ad4m7mOP%a8ccOm_#(?T){ z|9kv5HGt&34#D~r_79mg+E4Xuks6S5kdWNXF-S-(`!922@csYsVOKeL!#4eMprS{_ zm{MB(jzPm5Fo1a(z1lIL7?5N~!N7VK-ux;gBnS4l>o*+h#u)7DCQPjBrz_1HX4Z`A zzX3O2KM)xb1U^J&0G-ZNpwKW6gzG1P0wnwTaR4z0LEbEokX#~?5Bj%t;aES$;Mg!> zZr?OhW79OdZrQQ`Okj-B`0EPz0C^d~dW-C`N`OM4fOb^&k6ISVngLK8XAi7l4oWp5 zD+uzu3kk6aG8~YcD;A``JY1TmrCnQQ>s?#tHe6ti*AYI`+QK>%>)thB33KfS^$gjdiAdXS9pJCnD;!WYdEOQILLYK*Ofp#xnHV*x3@P?4@(0^u=Yd))&j`2&4SgP zJz&@Q4d^75hC^P6{t@2D-r*u7#4nLt9Fn8>aUgmA2$(PUIj?_EU$LJH|EWI25~&S= z`@X=CaNz3c1x)f9fH6`F0&~go-}&2je*?N{UBpJSb9Y@=D-@%zjMzVFfM9B_QOB(Mdkw}r-+OLq@L=BA4Eg`F)$|K4D$>J z`SF7~g}>AVv`1NU2k`dy2k(4gUK8pA$tCM`&4c;vUEta~2h7SkJs=MvNQk_D$rrxA zf5gB%YaDzgcY*wooa8}%`=9B;!@~=>K>2M-+JOzM8#07>JQXOvCdA+d`CC->8pE6a zQ@-EXqak_Hc*x%k*2(ju67K|m48?+R^W0%Neo9gA=bEdZOwk-(QO zfrzdDpyvaAzqUx8GZ8+2xkLU)Tn@?MAo0BD{2YKRuri=2_V zI!}dpx)d1CK=>nZrGxz9Khg!_o8g5OAi}`{c$9bU=i`E5Jp@v}XV>wc^GEVj$TOSQ z=x=$#-}0RQSQqw1jR0kD2C@QNfWEy4)cqDngz*a`4`tW6pTGZCBLCs@Oql0LgKbdaa~D_v*^a|3y6Ur+?|!bYm{KpWOH<-_MAB#&g*^`G-c@H}h8Zc9v32G92fUL#`UWS`5(mB{}9iGKJl|(}!T+2;5+})rahm`r|3OUl*ZBC)x`-NE1-ZVqKvPZ{Xqq_!i-|n|#ov!3 z+YJ8adGw$8{~RCwN4kjb83XkhAHnm7ydc=Z5coEa@ALP8aa8M}zsLU|#&r;*Mlk%U zi!B&SA8M!oHo7Wcyf_`CxApDwN8+H?!~c06{%83Q_#ed6vSIwHWCMUE7_V%HM()`L zpcnf3+UNjqv#|tT(aFHN^egxX*D#*}$bV$%KaK+;{PUpw6PErQZV8sJ`M4cNl@#|-v2>|X-9 zy^G)@{H{V=I{Y~&18tz+vjC9mUN+8v*60V|9mH|a|8Zh7tl5S9k^Zn=&u|d-hxhoI zzaG3Fa-CeuEa=O71>S|1|L8B8(h9t0Hh?3H6I;T281LU>85F?rbHLva%7a{|{B;h@ z&d!2&5fwlBzsP6@sJTtxHoXDtpd1$P9;UGF;%ELQ5EF8p4&28h{pBNn@Bccd3j{4} z0q<|{8Fd=gQNnvzjjzIZFxx0Wl%hnL-@<{i7>?@R!f;1z}6DUT_}nSHEon zXDEyP6dcdr^)LNK0ocGAOyoLys9#%{XLuV^^`pP?rvVVP3is&n9=`LiUKQTM1>PgV z-2#3WXBF7KlY!4@D?p_f*3NvL1j-pr;B9R6kNHUB^Du~AgL_<<(+Gt3@PV>;LVeWa zC4l%KkA3_uP`4&6GeEs`2*@SY3Le-FY4yrSK?2OzN5i~vD7;4iya#F#PK;m&%-0p{ z_xFH!yl2({a_!H3k=GxpCO`_DL*roHCkoyp49XI`3@6mh888QPi-`Xq_VJ(F0LZn! z_BXGc0-5mgWO$Ewn7fOCSfZdjk?}D=?fJ9){vlANFo+4c_SgQ_4KpAY&fQt?9%=9% z$?zVD@E&v1!ywPcZomIWD3=$kDMhaRwZ9##75^)WXc-4O2_-<`Q~!_8U+1^z{@VZV zoSVa^<$pxt!)=1sZ@^=Px&Jfz~L7n6sB6D`N6KF5sO3&b#Qp>k$V1n$gTk0C46 zH)h9on16)9{yfGYph^uJ^8wkhQIXS6QD5q!(H+LU3)h0o?TpWQ++4)!_d3zVul0dD zPLbOFt9nGBy-?n4GQ)8cfA)l3dWSMuiH1teVTF4)+#<#_KJ<(cMG`TnQL+ez_Lq=5 zaaqc{EAjH2W4@P9c0osmT}J(K^w9N53g_8!t@|O7mN;f^XGmu`5BU&;a**z=jFyvg zdx&7{44l4!XLz2?!GTwsovI%LD?JQ9@nI&~1%bdcK6Qb|HWmch7S;@Bu%9(xyVc{8 zoJ_-1n0qC9gD^Nc-G8K#?mimUn{CrGjpd6t;a{7m49`6<>b_6knH$wEMz}vbNM!LY4J)(h4i$GD6(QS;A@-N}hp$_|o9k#_G^>+t(on*TlWX9p#F#eS z8Jcn9B19wMPoutg((dvt2CMtky>j6({n3h2@HdcBFSuoxTE62UWj}U;^hkIT$HL(g zJEiCERu7W9QTz64oE2%EI`x(Csj-c^ zl@<5xBQlD+{AZ4GRJP4lWhgk?c}$FIUK%#Bm93l*oVpdol%Um{9`_U%!ya!!=_EzV zg@KNsAWQ5j&Z&zd&y(l%Jxd9n#R#&aQIZ>?m!r3LPN|!nGs)%PVk_jh#mjv9_M(=H|DlK&vt{V@_j}mCd)tw`8Nla!)-a!!=>zJg$$m*H+?K4nR4wl-3H5@iYXHY7e$8rD=c{% z!`GQC-5)Yl9eI{NY=K85n>Ig@Y2L2FR1w)b8eplrcxsK0t5x_NelC*;y@%Pj`bDO(J?)#rE48x$Q{ zIJ6_xW1)cgaH#!3rnF@g#wWtu6Q9t+Pg?nu8Qkjdu#BJzV|o*WeHUGD3-`54I;MXm zQ5uTS5KUoWcxCqZTX)p0EqRI-e)+>x$C(#&EIFUjk=2$IVB6W!-AF%^%Ta&dPt;Y7 zMkRr{v|{LxOMX$NVa3tQmiTSPKVmv!4Lo@58xVfEW?6#vrSxdmr}ct`A_`gO z0**`A#K$gfGfo~y#UB5B%HG0~+>(oDw zUgMWZ?;^@~TAQ7g(zfBf&12^rdI_UvDazYHQ&m_MJEvxGquV8}y*>PjCiaxm4nFF{ zODvi<{;7lOPfF;fFIa|^KkX-64dmycPOK6orwRA-n;b96Oe2qA*;cxu6omiyWY4GL zDa}UK+0D6kQEi*Y$5{w&V1C2AL|OlV980E`p;nd)!)zn$GI9OxqdU{_?uEiBmVGd->>0j@-aD2#r>hHOKe?%nI$EzTKfmcMTHUPtG#u8@yDS`JMJ0~WTg=j9EFBSUeOR%hYwk{K1E zw6d4$7H(I1Y3YX*EtZdMtmHISj(8c7(u|_*(YbeS)9uQPx~nh~F)xd~Y&kpr=rl-d zyQn}p)`6`=d{&IF#^&94mgPr!G$yZ9tiofScsT1Kg!1Ou0t4ezBC^&rOF*(`3kWvDFk5 zP2JE=l1Qm8>0PxG!}6Ng{=(#(5^j0ys9ma}xnOF4q-xlW{9tMWT%l{_wba%HteRdL z!zX6^+Q(^k#$UDOgx`t8sk6DR*=3rp@v$1W_GJl~PLS_;EyYvS2Z(HWdvkih(<%!$- z0yML826|{~vXko)Upz>_Gq5#`o{tR8iZBbE?K`n4u;U%`sMt-f*i|pMibdTuy-7A| z@JXM@ILQVXKdB05{FSA89w!;~X?_-(#Ce+@lx~?C^X^N0y;s+|nJ0^JG^IPbk8Me_ zNV(MVRgtnV3kG2ft>V6njF)SP7Co1Z$#VW|yOm$*kwyifD2LLcmAO;oo=GX}IWJRB zuVg7Fi!K#C=amV+{AC_DHWa5D#f(!q-ubQ6wBA$l@whh;$$f#{htqXEp6!vki49D7 z5-;+wHQ$mCYB;<$*>Kk>aJXcbDib5{$s_^(bPn$sEX7n`#xkad97+~Rc&}^T3iDMp zDV{pxg3?zeBr&#-As(Hg7Y_ZXzI2AMGvpPm34P7%u#R}$i(G?l@eiMeA2BJMF>tl0 z#5Q2YlDTQOOG&zOY24%XB}(ABsBzj(RF^D~A?^wF`%X7@34*np+b^-}6OszvD<0k| zux|DVLu1>@=gU^xewz|>R_v0Mp;3mnq;=3!!(Pma!ABiSBG|%xiwj@gNu4jz7Uwuj z$liP|_3oo~zr2-kmF`1iTW@n>Z;hS|ocAhK6V|?{mp5HVFL3IN`-s(|gT=XMb16A` zp+-CR%EXng_YLBSu-4AHxi&l&s38%$$l1+D#UiRT;(i?ehVbm9a=eEDRj8i+cK^{E z1}|H9#lNy0Q4BQiK9cSp;huG3ic-U2(@tK7#{BIz8Lm${84G>8yUe@=`r1c=V?&_#xfu3ZaZUgaEKQliCG@?@Q&NM z^*M4&g27wZDw(q+rTX!et%qaRs~OH}HjR0im9ZaxnkX?dfz5HZ&rwG#xYg?0^=^XT zry8Rjhu9xfWXKF(EdJtAa#UBg_wJ+}wLab2M8US$j50I9#zR~soe_~V9UXR>FAt-` z{dmP=X0cDmxo!}@;ZY^Op6K~xPA8#Q>>=m$w;h=#{*9SS3AJv9)3HUSkfdgg9{KH^NFhzu~ykNiM8EUR=^&-AUCv~U#q}Uk} z9^8b?>tmhrVvF&(lwx0Up9}_=P`InSWo;2pk|U#?ty1KzLDLfFJ(jH6NPLPVpP%u( zryF6_Yu&APd(+$=i~4gG)Mi#m=9!db{@>n`KJk-05z79$ZJLT~N~+IClha{*;DX=1 z7s@uL*j+C(27PJ0QgKss*h#aX#JCZohJ_NldvUNykDAdWy%i-jxpv4TW>1rThFmze z;*E~uhjWZwjN$ch-GlTiH~i|4`nY+G`Qu=Jm|#pu;=C%sAt|79yzw1#s%g2yn+1AdX6e_G@#-<|LCSIlGL*1il5iRiq(~d$}4&$Ntnq)g+ zIG62V>fxMbJC8)^y^al+%V%w?wk=T%Zvt4Zzds@F_$9&d(yQ0DS-iZqx_-xe7Ux?k zc&$0{KR2)yhQK7ZL=Tw?DJxmMPh(y-`VyBTeDGN>UOKlx z@hstn+@I*f6=r~DXO8iPbs>tiZ0F@t8t3N4!0k1xY(TjI&Y zgj@CexYAMzc1!#FuW#mefU(n~+qnR1@7|}qi)NftT(Wsa85Lz zZBU+bG$!3M8QP@_363QG!qwl|K)m@r&&UDX;^0!@NW2&O_877J>eELxNu}bU9DQ-Y zfoDCZ+P(b+VuSL|# z_^MK!$yv+k(OnC!5r!pWnP9DUUOgxI=#yLlVTZ`D%AKTK9i#JX{32X3c&g?fBw}`a z^DXbSj`|qJjrk>sMCRhl+qi@JFG=_Wt4Unmox~!HKZf0Hq^6hD!65(b#kCMZjF{{# z{(G3)M^gfYd0ygDN?gboczz)={LnirQ4Pvv{At&?BLv({!>)(gwcbrDIE&^e30ZG@ zaPefg6G=KoehuPRbReL-nX@Qs-u|wPWBwBLJyjb=4f+hSaGOaY{0y@c8$&7;iZVUv zH|nDF=1ncfi6reu=Z-}h5p*uZE@Z^IkJILI=NdeTH)!3_&${QCQ)opY9bs|io|aGO z_S6f9mK{uwWBT?SpF70*8#0W^2xLC6>ytV=7P=Lp*>zldMLQ$f(NlZj*{K&!&nupb zx6x+IX6KkxROAkwz4GqO+!ssSq9kSAuQhMT-?=^Kei~hw;2&JR{Pn4rrN`2HV=7hr z*tYC5tDe_QOwik(^yQh%c7MJuCJ;ZtD9489?Q`@&u;(<6(FqNl9q(Kj){2z3*43|X zXiKRyiP^P1QoCL%S5z5A9Vnlm8b2S`5qTRwmb6)PuV0StHA{yIrJ~Kpv%TNsMaW`5 zUo-LB)XXt{`xMJZK`esOPgKmTHo>S5%S6;Dx;))#gy{taT?y>8U0+A z{4P;x>8nMFKCj8y=92@Yqvq}>ue_TZ>nD%C(t?p^GDJGhqvO<>j!V_jQ`kew{E1TY z9J6{?CSS&QRRN_-cBx$1$I7@G!#4W@n!|~D%#Y(RXz^rK4W2fa_>ri@_g7U6=JDrQ z>5BOn)!*q5Sr1^PP5m^)sFtlfobNMW{n&^r@DBU+l^eLMyINxPl!~v733*I%XzyUw zo93t#WX>~^wKAJMYtTr2AOBL|FaZ}Mk*=qk6}4fqHUoX~V2)tOC5Z`XDVf9f&m?&c zVQ@8M3*X+juX*0_{2_O*kp2W=#}{uos99gu3fsg9mx&aqOectiKDXnD4>Xl!aNNtG zciYC~#GAF*(Gn+Fj9zu1)P8dzdB&k&h4Yrzp^mb5vurN|0%lonb}6eZZDfm5ON2^3W5k;h4HS8j3 zI&uwl6T8F{#ZY&5?i-^n<);!WnR~ewd!FbxSgW?LTB2O15k(Z{Uucpg-x5n!t)ds~}VNj#rX4JNNFI z(_CSwHtFuOySvVZA8L*-j*vyI-nk+dz@9hld%n8lY0AS_<-siXn_O6%@PenZCK<#3<*`L+cRHGCJ2AYN%w<_W9PyN~cUi%9G`5oWTK~lr2*zsPg1W!+7Ek8Ia&m5LG{y``0a2vUcEpVeG>1z*o5a%Ep8I4(^T$XB>UZ~N3YAAh)nK^ zz0?V^pBmocKYn)%77P(@^rVfqn95Q7`I7`$}WfFC;Qpqr7o9|3pWS+`G?UeM5 zp@%x-Rn;Vaan36|hDl8N&cOkU$FjHiNv6+_7^~WS(Y})QsXIYQEck2@| zgNa@^@ zxEj@^)wl^p#zQ67iR0!uyDcUn8m5^-14^A&gL7P%D5Gw0rqI&v;q=mzN<^(%iQcWv7^e4Xn1SC`UY=E%Wxz_Ke`CKj zI^WoV&QijbNT*@T_DydaeWg-5kGbjWLp(aN1m+tUDtwdWE~htbu1(%+vKC1yl&R&*K%DK7EaQ?RBtc>xmAs%E9>!$z?R4j3%Pl%Yu{w&YY7+U_(l%I{UJ+du_)0rNw;vEK1D4+v3l^=&DTsyV;Mn~-oZSPifmV1CBU3IrB zN9*0qs#@xf8U~XY3#W)Qjo1p4lauFNhYwZn_O9Y*T1?CNJtCYUzr;UD!H;!PfJpAu zy~~s4z0tFGF+88LsMyNOtB;1rm2HR!Q(gdihou{Bch#D!6$%)!t#Qqj?_IBy zagIA8^d#V7(u3(N3^Q7&#X^tTt1S%SDYSu*X$7)`q{9ZJ%@;}<91JErT8ILBwjHJ(!% z3#8?;=j9b8G|Gt{+pZBJTc23>nyLhmyJ>ZFb0x72OTOyC^*1IF8qx6gb|%!AC#-_+_6P($y^R%T$0Hb`F_>XxZZ|SF zdF(Q|>lV|oy)}}Bf+4=bQQYirK+d)o@vV~EH~_^vCf0DPD|2v?xhwqu;7NH z-AcOILLc0m+Tkydpec^0$l)){KGKCdI37G@wPqw zy-H)*ME7fbhIw_;LGmP8A3BO*FFcvLx`m;N_*~zWSMTTAH6?>IQ&Gu5_uo}Zj%M;X z@=jPq=mukQwJO1xI zkMp%uXQiK3xOrDY+nKC0nOaLPRVjXOg@II;l~5v*FIC_aPTHx{z79hSIUmcdN%L6; z+T0$h(PO+fzCyyFvi+5kv6Z@;BC9RuI!@;`og8Z|@5}uJIv2~E%CZg-DM=RI+ti#V zOLed#+-Bch4*lx%LcQ+tY!Vss+$vSDVFWlXGNh@2=~gMZDDGRrmpSsDXj<0DC4tc3 zsOGRhHeIKoJ69*Ug;M_%PR&xS%d^o6$x$q!HX*!;rev_Xt`KZ7= zo2!DfnMR?_kfJ8f-s_PGsu6lO!hGcmeqFDpIJHYoGa0*?ha>g530T) zSF&@Sd2}s8Yv3}IhZ1UHWHC*a_g0<$oC9a@_2tZf=NA^Z?<##k1%zFWQ$CVT9Hu1U zNQIj)!x*d>)@yKDaF#G5GFvR1yz^6z$UEX01+9k-rKQ)Bl=4fR)t&n=hP4;or_tXd zs97j{a+^&j%tN58+va_c;#&Hs`OQ6U+9*!^N^_OtD>pfNl>R@u-hoLNEojng+qP}n zwr$(CZQHhO+qP}L?VdX^5gYq0{zKI{RT)oaWtP@6F>btBK(OI(;e+Gg0EyI&d2GCA zG+x)8GON_qfzLJB#0waIwaJ4uII622vL-#~U(zYX|BDa3<*pDmOCEAPB2ZJsxH}%o zh^k|{)Nx%= z??fZB61i0Q&%lf+w=gH?>JB>DB})&1f9OX#=|_jB?${W0d{Qa!~O#PnJ5$k;#*QP}P`@QpP$J zq4plMQ@dlz>ucF=obMy~v=+l$)%HY%q2}tQ#zCq8lgG*k4wt}-qG0e>xI%}=rSuC^ z=t4zV>~(S5pcr*7hQ7JnYq3BlA$q{c<<5;j4~rXK2UCviVMuXx!7z?# z)ij{7Wg%LemmQo{*zP$>? zW8rhJ^VYK&b`v#30V+CODbJRxTqlqytnuh;kXtti*F6*q+TAM?F=N_d792U#0l!8faUtZGbxv#N-)pfD_Oh1CG1 zaaRq%@TTn@2G##IvL=)UFb!H2mbEQ2Vpv7cg2nO#5Cz34dXF;QY^?xG=2VpGlpov> zj=kYW$%D*RnKfEL*dDoz6k@6<)9Z6K?OgFX=IOcDLL#AP$2yf{SbC&^RyfjFXM`Uh zi#S+;oJP9RueJ8Ax*X%(W=z^c5niW}h_!N~4QvB0o+O=3K5ETfLJ^IiH@+DlBP1xO zzLI*bqB__Kb&+7Jw{iuo7ztoXDXK!Xgu-)1EN$*_a{z9ZCtVTI^JA?<=(tu=bkW%^ zx7S(8tR*y{toyv$^@IzSZFXJnTrWc5W>|TCgd0USl0r?tVF~-53IyP4BT^}(*BRTD z)+6!=t;S>xdlRH|xuKsdm)|tfHkm(sYi116{Wr0f2kb8~6^K0ikJ15`2uHZ5ev~KQ zL;80a=^pk;9q4DkyM@;AEYLoWutuiQ-muKe?#0dVy~89uKc^%k$z?KfG^*(aHgscR zwHi6|WR15bu$Sh#?6Jz}rRX~(>pN$%I`J8}dJcc-8uLFLJT>_zDShv!eZuElc|(^s z2toK}=wM3QDw9THf7k8^Z??C{qsYU*;CnSSBx7CM;dGl}BTmD*&ruxiVi=*!vb!NM zMTSa#xot!WABF1FiIc;GT*DU8+p2u>kzlC2HzR_QZyv>(RasPa%A>9C^8ua7CLE4@(mO-zS8SZc661;k%!Xb@ zrt>}pRDb{pd$=_vk+_XGPNacSh0eH5YHwaSV2x2{O5u+JzI3e3ep}Iy%t|BFD2@gH zKm@LF3v<-1VyS9Hb-a(F03f#IhM}(1BIbBK5KB=t^cyW`V+D-KtO_6QaTo^_S+Ar; z)3Dmd5qbNOshsDXdnPqSTSOo(ztln`Khr{_M-Qr;R8uc_{o4PJyOj{;#-RdbdOb)6qI^YonY~*<3iQW zSBMAKt23Z*`KY4d1d1(dsNr$Gh6LY0Q8RsLVU%$xnmg@Wv%bA)5pvU-*7{1Je=e)4 ze6!lyL1PsBNt|KL$kf4== z^4kPKtIqT+l-FaT7Lk7V*&{#!r$Ngum8|CMh*J7w3a#qq7{D8iRKEI%;|0J{GY)v0)o)9j(UsW$GUHwDoL&hzg?P!lgrJB~_Z)rw z{n5C6<>g^KIVXE3GO`kFTJw)SF{&TF44DEOlkgfm5Pc$6FmJ-GJ8EVon~>5GP^e_xhz{oYf}^7;$G zFw~vS=0*^(rp|ovqFW}%lSKoIY_ugdthmJf;&GJ$XRlLV=YCT4gyXgXJrP{#^z8!8 zqHvHnce5Jji$vaI7U=9fqH_Xz%I|^_m0bU6$seW52Z2hjXKFsjhz4BX*uewL+@BY( z&s;nAh6PSwV6wj~%-^{C4Q!GkoeH717BZ;!xlIQ7&j*BZ)%?8^BYiXDbKBmp_#gY| z*MQ@XbS1*Xuai?1QLIgT1x`tq^4Uqx%#efZ@hbKe-h{8JW|)u8*^Z>7rdXQDX|`2m zpeU@EUt<%rTIp;hX=CbO5KkDrE{0Dq$=@X|pUo6i*b~Lys*iJF#EIdBpHiw0=kE~R zg&?G9D}_K_`Sk%lnKncH(@ZO}6=QNICC;u}(7*;O|Ec`G^6IS2?OaH?-|F?Hh z!O+>+-QLOM|Hx7QiBYX7`}SJ`Fys4)@Ax%*fn!4J?SXF#p>|bWX;vy(E$LJwV0Jol zi@CyusDIw~PsIojv`bphk}6QU_=QluR_Zn9fVrZp22RHq`%c zhe#FV;&?yIHa$m&`MUPtCmpTRb?Na{E@V&6h(@&RPH z8ZPFnF8W&_l)`X#f8^e@ip;W=9ZtKPt6ODgF-rV}Qcj}qNUdA{)o@!1?>MP{`6-%~ zOGb9oT$k#g2Cbli=#P7XNwltSW7EAXQMvX&&%Dx2U>&v0sdL;+qkFnXp+=p(%^VIW zlQ;m$*46laZVGt+V1$eojD`|rg6s^0Z;&W~5>Hg;l%~`NepkV%I9w?kv&jB{NX*rQ`VD!N%|)ir{>r|OzlKWR{1%MP3Y zKOsJN<{2MWi>^9@lDV=uKG>s*eJUPT--C+c7?*zZd<139fm31 zB#Eq~#gev73gyQ@<433+Y^39Isp6KXeG)OL_dgan_c_Ja`u+cgEupB25fhvTHBo-2 znjT~(RBrFSJG+G+CM#BA$Vj9rlun@h??Pkb9VKO`Ljcj{e}DNrOP^RuogT}2ePI1h zWQ1gl6l|shlenocamf+tChqyw5+vQkSrf8DmlDE=6U~Bv*VBo@NOnN#R#NO~l z^^o((Cl~MH(!Gm8D9Am5x#!fW}>2wG@(M*f`1jU-xmCE zm3Pud>2Pf!cv+nPHHJ_k=X}q2(A=R?YDme^rk4fuw?v4Aq&&=c%1)xZ$c&f}ohTJg zHOolI@{uXAL?G#9;Z zfLBoB*T|b1^4h2a?9^9gcA4OnTH@~Y=wTn}rHQ1$61itPM}vDM24;ZV_ATkZR_<(a ztZO|8ZpRf0ueJ;&BRyG2mv)48@*zIUef&cms|BE@n{`Ql2gMaWLc_D>E8+<{sk~F~ z#^+PjG3NG|Z@Sx6&oBrTm-A)soC+96cOi88nILicS`3oh2Qy$^K4gqH(@3tDMBu=! z`|V$h22t4uM$Us!$w}(p`LY+R-*hSa%9Vkk7ZGt?OwkhLO?|=R*7P97NV|4;SjFS? zS*$z<&q1pwHsABs-N3d1v-2M1A0*Vm#&gs1mLEUo3FEZF#Bl*?#DZ$y^SytWP@?Jq z+%1Yr+$ZkEM@^wc=tN@VG~BReR=zZC7X?ldGlj7ICo(n(DtCy%{h(nOJ{IbfXsG0s zi!E%;&zQPgB6A2CYbQ=b`JpVcPdBMJRHXf+NnK-qzi{P#A)(YlsXTmd=TF_p7t#(p z9{z~dO?%27+;;d4D)TZ`Vb8}$)iqVNS0cX)6Q;qY?{?kjYK*?a(rUqNEXJ$_^8Qgi z&wYpuW$WP(km|N@Yf!wRMm;;4VKwyrP%0EQ-ibCg?~1}Mv7Z3HlRIV62w1O|d&o8c zyNHeAYjtp^EGA6sCTyPF#Ianucf=@@wp+GprULE%zOo+R{cUV8Ty>=}&!*;sG zS!4z8%jD02QG>74TIMCQiTbag>Jgjcp~zTel?#i8!v(&YbOoVsxc!xQ+G?};scut6 zhBS*LZnDLUVYQFfkY%-LZ@6;k3!cKc0hx5H_;CT!kYywjzn1Y_AV?73P0!RCR#{6%Z+N2b-bP~IE~@*h7AcXrw*Yn<_%ZeRy6%AjyR$T zm)BC2_g)rmhYx+YjR-P_DWwCb}rElHfh^Rs(z4`py#PG^3D3(G}gjc}~NauK}BKOXW??owm>Vtn+O6TC3kN zN)K2n`9YuR^gIrBH&7(jvRM01(h6VnaQ)v^R~={9)1)<5c0s&!t@4!4_)7j#pVO&m z4CkD;)JD85p$)Y{4KcXk?}z`#EWrNimj_J*0FYbwe{xLJE$zhYoot=| zzuXPCyq3<#Y)$*hseb{AtKP)x6EBRMWNti~@wE0WkBrvdOrF^#Iw=sEI?5$!B|auh ze?PA50C*e{Q+X%1YP>3N(I8l{V#V?RI~xY~!|xQ5=bNDMWy4=QujHOddMDG3?2~+d zHpaoV{G9|CK&}ZicuNmnY0bYTv5mL0v+BU#_v|+eG01KV(4J@BDz5xd7^<@xQ_OjL zPXp8kI&(uYvPl8Wo=7yra|h=`^3G{8n}$jGPv7{5Mgu-?+8r5T4}M4=nqx%{IiHup zkmazCZ$^TYBXMLra~=a}jswbR^Bmle|{AvIpf`{y=U z5obt5&>nZ;iey^3B$O`b^2li;+%{?F(Ydj)1e3;j!vnk{W{8j8@5aC4Fqjru%`@Sd zhCd8uK6mm>t+;}*4s+|xJNfi(8|~ZK+S=Ft+G6n6^z55!>D>A~TOUW)>;52O#hfwj zbH)Z(BwF;qYh%)?hh9-!4qh_MPI*5(z6ZVUHwQU<^VS1@JT< z>+ZyEjxWfvDrbyrQ`W8DFkL`?vT2tg$OQ~@$U5gzC#_sQP<$WYlB9<3TCoC1&kx?6g6;bf~w88$rnm6;FZ4cx*u}K^`9t;ul{9g|r z<}gr=eCE?ImXOSO(x3C`131Pe^E5CZ&glkCl1&G|9=wm~nCxK;X8<(-{yAmMha;b#PH9g30pQ(Ma1Z~s zNg}~+dhyS|2WpJ{os@00WcKP_Ed!%Hx)F?^My)Qym4diZLAMRxg;-K+1QnJZ(8$2a zp+ZITjMBpuUFg;)C?7z!jeC)z38K8Z$pAFOVKAtDIV221IjC}WpI+!-o$WmN!L}L{ zbDXu_+uNwf{d!&yS@YoS3z^#jAU(iwyqSB>!zE{+j|?C^M(P_kZIQral#C-N`ec)> z5r8!H`BeHLFZ{f68T-_LMG@-gJp3lgf0?FCyN^LKusJIG)zoSi(4b|02-Xn3z?P=alle5o{HE-FEFz_( zg1su!XnM!TIOi>5kDQ>(Q{9dIaEo$=Rw-R{plSkiF%*y&<(eRcjvN&%rLe%Y(RM>P zp^@@nN1*zT!6qhW;_E#l;bJ~{Rb|r`oB%zmrp-_2Tvb22Y*j5Zd4XfYG4>je9%Ic zDPiE%0*wHHpF$UGaH!-)1}w^aas={ccsO4KLva=CvJ=pJfRxTCA_w%I_MTXzjrfIr zxJ==Ja|$&q^y5OGuWAg<+ug%*y zp>4FIhqPhoNZjtwSOq=M`F>s8qR8LDyQ5rYg5`5pudz_x@%9_E%}$ z+Nv$r!eP|nD1}=jR%5&pRCAJ2UviM)j-NA{ zaks;UC2qPcMNM5SC)`j#44`+o0fQ;Tb-7HmqfEOZkKR}L6g7qqdo%bJTreUcrWQzY zKwDs{9fmTw2*%5rIhX=cb;dFIY+{F~fkIvg05ol80KcOV&b`o;>{^&lA$_ADk4yke zKw#2nkDBJBMY!ZKK=;nLtFr?=sGZTv&-wW-UZ8r=|z6-xBX=q4Z%r@+nN zmT_=HP`a6muUtSyI!SHxs8kC{8vevQ)6eW}!M@$NA@lF~aB?$#xcaAf`jB&@V>sA7 zeRho&O;;Re=KUnBC46eu4s;pSKM^y2BG zf;;A-UND%NFiw7YSQ@GpxN!8D5?1;UAgR@tXTN%xn;pN6p9y*@3^L8v@9wTHEqc4+ zivG2$UWaJ_&aY_c8E&-ASv=3I10Ef6pz6K@HBEFY8&*O5rA*N<7Oa}@A>~lCz z`mCVmgNjsQFIn~gou?i}Y$@;Wk_v39)GV2PX)>GjEpmn+E7FBC5!T1Q+{1KL?HQV6 zzWAj{w*e><I96Rb-$eSAPupbBygG zsGo1c!DP#R9SSrOkO5ZX$do{OLT?6D$-Kr$iS7~s%@-KLm6FB(zC^nYLQ5P56dd50 zQ8HzY3a9ir8&l&Q>JcCE2HuD$QKaOGWijO|hTBopj$LpAmnR5Oy{;8dh0FmK zVk=oe3~5#A6Y*-(X!9)9|CUzWWTLrO8>sA;!fl{LE|-*Cy5b8O-2Yf^Vf^-53B=wZ zp~?x@$|Wj?El$Mf+)Lb_)fEG7pIdSnDygi)pAhlWC#Te;$ipyD-kl9phBw-I%#~xM7H1eX5L9F_B|SA`r~B zN}&PVqIjJ`>?dZ_-{5K%S?GHLX(H`J1De}%3cJBd8Kzj3Z|Kp(Aj0%}gG{3}<=?IO zrapXecypu==t8iQ`6&y3d-1>v&%PftwhPHlD`Rg-McAMmx8%qEMoO&59l>k=349NX( zKcCO)tzmju zV8Zpu#wT$Z{<5l;hj#_2ErMoPw}aw-HcVd#oHm&mk8NOF?YSmhlU>z}v1b!qi1f~h z+WeuN@{69W>J8h5{lNC0*YDs=TP0Y2!Sek2|9RUJcupXNVe_Bhq^)sCk+Cn4l#6HP zeCpR;M^^ENG8m{F#=$yNERY=mV$(aiLxG(WUA4mp>pufHhem+9&yarw3YZPBfg7Pz z^|9@jhV0ZyO&p5|Hbjlyrh;uY2iD5Ait0^}6!zOzVU|mWne=pJ7!qhKQ?JrmnjXWS zE##@%Ou8Ks9qFc$g)-XOaSc2Pb973UO@Uk(NdMQ;hHP(J99*dJ;}e)_>W_hMiNEC~ zT{WCFV=t+IgNOO51DsYZ!)TQ0P!t~py`_1+l_MJ5?3KtRZ&kQ~R%qowm2Vx$DMA0N z1YF{5!U)k7a6`N{(4L2${1Xdn5Wn{+_$%Fi{vtV4B}}jeRm5ek_KEvLPaiq!%3}Rn zRn%nhGlM>*q{@M}QgL{su&*UcoodrREM$2n^ssrBvG!CqU0o3Z?fg)Rh9LdZk3C5n znUw=%;D!06>caogMAWsDP`9YD#Q@pd;6B+Tg+XWbUPWpUK06L`=k+LQ8*T%wDfg{jAftMeQm8#f9lb&Y2=4J=b zO3M%s8<%u2s%hY^y=m>|F10OfLw5y_5*11P2xzU}ux^Wy-)Aze7=YfxITp+g9+0C3 zEKJ{lvt?RCJ`=V==k%Fw!zG#)Una8=X*W2BZ`$^PmpM2+oFI0~HF}hntIJBH4>|yLyGGuTWuKd#S3i!z!HH zf-URlmaWD=va#yGjE&&LZ5UGvQ$uT|R?TJ~>WG=9`)TJWmQ6N$HtdpVlA@T{w;1!( zn@4~<{Sdjom+m{c7oh6_Co&&D*F_a_(1O#+Imv?t=i1= z(lw+{&BcW30h?AfM|CU~Pplajfa_U-h3cg(b@+N~L_h2-`c!PXas+Y zm{uXp>cYjU)l?qUu)xk}ffVgqn|-)*?$xuM7eW9lmqZ=s!k|G_vjJYu(P}%SG&d$% zQn&x10R|fpe0A9yxpBNq-F70-P3j;R^$QLSFvt0U@ca&p<&1Yc@8rqO2rwWABLv>z zfekoqcLG9{%P?NXyUl`)UJ0KReYj7EqfqR^RVG@HcBe+RjY-@zL+ukFP^E$lu)ImNiNjzZJlVW^`U%T7ZilQH4UV)r7y2UPu+M z94yL(qt|OusfGSeWFcZ0Ots-oP^X1kGG=_f`R7&CtECkYoUDm1G+)Dfi6o}C_yCkQ z>bb%oU!|aCGtC`{dZ6#TwRRcqxOQI&IzAcxgw+mgXo-oP2J09PtSdk?0Jou$!)G=P z!#r7_M**I^o1mRr@uWoS%AfZlGt(k>XYlM;kA){fy_h!cPWb83Og!ngF!a1 zT#6Wpkx2p2x&bF2V!`C#A7rPFFMC!2zXN~dHz#Ov_5BGR_2Lfl-*!_t=j+meuaxN` zT=DRXk>$4J8CBg%tDaVx;;{8N^|-NnN^u~9Ngk*NVi5OcVH6AtFZ9k8k~H|GoratR z7q4$F6*Z=@x+RnT$-q-pJSs{q6^hq=2zDCWyJ2Drni#AFP@e2JsQNS_dmfrfWRl4u zEJcl=#$+x>dnk5ehFdM|jRvh)gbaP0B)Ydi02FfL?*OGQ6Ecq(r+dSRZD}-!1*vQ? zW@PDbhV_|AYPgonbRgdo-Lw&?H}Z6{jhw2(s!P@^+FKh&Roy@f748H)jL)26do;4@ zQCnVQzT%$44Y&>Ath ztgNn&g*>oTb#wU8c0YP5Fn7s)B0k(zjiWnX9z!L2p==12P?0in?^(9(%0D`=rKn?$bC6tF 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 diff --git a/HandsetDetectionAPIKit4/bin/Ionic.Zip.xml b/HandsetDetectionAPIKit4/bin/Ionic.Zip.xml deleted file mode 100644 index 24000e7a..00000000 --- a/HandsetDetectionAPIKit4/bin/Ionic.Zip.xml +++ /dev/null @@ -1,18168 +0,0 @@ - - - - Ionic.Zip - - - -

    - 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. - - - - - 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. - - - - 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. - - - - 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 - - - - 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. - - - - - - - - - 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. - - - - - 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. - - - - 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. - - - - - 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 - - - - 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); - } - } - } - } - } - - - - - - - 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). - - - - - 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. - - - - - - 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 - - - - 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. - - - - - - 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 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.) - - - - - An enum that provides the various encryption algorithms supported by this - library. - - - - - - PkzipWeak implies the use of Zip 2.0 encryption, which is known to be - weak and subvertible. - - - - A note on interoperability: Values of PkzipWeak and None are - specified in PKWARE's zip - specification, and are considered to be "standard". Zip archives - produced using these options will be interoperable with many other zip tools - and libraries, including Windows Explorer. - - - - Values of WinZipAes128 and WinZipAes256 are not part of the Zip - specification, but rather imply the use of a vendor-specific extension from - WinZip. If you want to produce interoperable Zip archives, do not use these - values. For example, if you produce a zip archive using WinZipAes256, you - will be able to open it in Windows Explorer on Windows XP and Vista, but you - will not be able to extract entries; trying this will lead to an "unspecified - error". For this reason, some people have said that a zip archive that uses - WinZip's AES encryption is not actually a zip archive at all. A zip archive - produced this way will be readable with the WinZip tool (Version 11 and - beyond). - - - - There are other third-party tools and libraries, both commercial and - otherwise, that support WinZip's AES encryption. These will be able to read - AES-encrypted zip archives produced by DotNetZip, and conversely applications - that use DotNetZip to read zip archives will be able to read AES-encrypted - archives produced by those tools or libraries. Consult the documentation for - those other tools and libraries to find out if WinZip's AES encryption is - supported. - - - - In case you care: According to the WinZip specification, the - actual AES key used is derived from the via an - algorithm that complies with RFC 2898, using an iteration - count of 1000. The algorithm is sometimes referred to as PBKDF2, which stands - for "Password Based Key Derivation Function #2". - - - - A word about password strength and length: The AES encryption technology is - very good, but any system is only as secure as the weakest link. If you want - to secure your data, be sure to use a password that is hard to guess. To make - it harder to guess (increase its "entropy"), you should make it longer. If - you use normal characters from an ASCII keyboard, a password of length 20 will - be strong enough that it will be impossible to guess. For more information on - that, I'd encourage you to read this - article. - - - - The WinZip AES algorithms are not supported with the version of DotNetZip that - runs on the .NET Compact Framework. This is because .NET CF lacks the - HMACSHA1 class that is required for producing the archive. - - - - - - 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. - - - - - 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.) - - - - - 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). - - - - - 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. - - - - 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. - - - - - 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. - - - - - 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. - - - - Close the stream. - - - - - Flush the content in the stream. - - - - - This method throws a NotImplementedException. - - - - - This method throws a NotImplementedException. - - - - - Returns the final HMAC-SHA1-80 for the data that was encrypted. - - - - - Returns true if the stream can be read. - - - - - Always returns false. - - - - - Returns true if the CryptoMode is Encrypt. - - - - - Getting this property throws a NotImplementedException. - - - - - Getting or Setting this property throws a NotImplementedException. - - - - - Issued when an ZipEntry.ExtractWithPassword() method is invoked - with an incorrect password. - - - - - 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. - - - - 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. - - - - 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 - - - - 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. - - - - The System.IO.Path.GetRandomFileName() method is not available on - the Compact Framework, so this library provides its own substitute - on NETCF. - - - This method produces a filename of the form - DotNetZip-xxxxxxxx.tmp, where xxxxxxxx is replaced by randomly - chosen characters, and creates that file. - - - - - - Workitem 7889: handle ERROR_LOCK_VIOLATION during read - - - This could be gracefully handled with an extension attribute, but - This assembly is built for .NET 2.0, so I cannot use them. - - - - - 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 - - - - 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. - - - - Flushes the underlying 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. - - - - Gets the wrapped stream. - - - - - The count of bytes written out to the stream. - - - - - the count of bytes that have been read from the stream. - - - - - 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. - - - - - 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. - - - - - 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. - - - - - - 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. - - - - - - - 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 - - - - - 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. - - - - 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. - - - - - 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. - - - - - 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. - - - - - 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. - - - - - - - - - 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. - - - - - - True if the referenced entry is a directory. - - - - - Provides a human-readable string with information about the ZipEntry. - - - - - 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. - - - - - - - - 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 . - - - - - - - - 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. - - - - This property is only partially supported in the Silverlight version - of the library: applications can read attributes on entries within - ZipFiles. But extracting entries within Silverlight will not set the - attributes on the extracted files. - - - - - - - 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 - - - - - - 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. - - - - - 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, or on Silverlight, using UTF-8. - - - - The content of the file, should it be extracted from the zip. - - - - The name, including any path, to use for the entry within the archive. - - - The ZipEntry added. - - - - This example shows how to add an entry to the zipfile, using a string as - content for that entry. - - - string Content = "This string will be the content of the Readme.txt file in the zip archive."; - using (ZipFile zip1 = new ZipFile()) - { - zip1.AddFile("MyDocuments\\Resume.doc", "files"); - zip1.AddEntry("Readme.txt", Content); - zip1.Comment = "This zip file was created at " + System.DateTime.Now.ToString("G"); - zip1.Save("Content.zip"); - } - - - - Public Sub Run() - Dim Content As String = "This string will be the content of the Readme.txt file in the zip archive." - Using zip1 As ZipFile = New ZipFile - zip1.AddEntry("Readme.txt", Content) - zip1.AddFile("MyDocuments\Resume.doc", "files") - zip1.Comment = ("This zip file was created at " & DateTime.Now.ToString("G")) - zip1.Save("Content.zip") - End Using - End Sub - - - - - - 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, or on Silverlight, using - UTF-8. This encoding is distinct from the encoding used for the - filename itself. See . - - - - - - The name, including any path, to use within the archive for the entry. - - - - The content of the file, should it be extracted from the zip. - - - The ZipEntry added. - - - - - 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 or Compact Framework - versions of DotNetZip. - - - - Developers using COM can use the ComHelper.CheckZip(String) - method. - - - - - The filename to of the zip file to check. - - true if the named zip file checks OK. Otherwise, false. - - - - - - - Checks a zip file to see if its directory is consistent, - and optionally fixes the directory if necessary. - - - - - - In cases of data error, the directory within a zip file can get out of - synch with the entries in the zip file. This method checks the given - zip file, and returns true if this has occurred. It also optionally - fixes the zipfile, saving the fixed copy in Name_Fixed.zip. - - - - This method may take a long time to run for large zip files. It - will take even longer if the file actually needs to be fixed, and if - fixIfNecessary is true. - - - - This method is not supported in the Reduced or Compact - Framework versions of DotNetZip. - - - - - The filename to of the zip file to check. - - If true, the method will fix the zip file if - necessary. - - - a TextWriter in which messages generated while checking will be written. - - - true if the named zip is OK; false if the file needs to be fixed. - - - - - - - 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. - - - - 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. - - - - Provides a string representation of the instance. - a string representation of the instance. - - - - 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. - - - - 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. - - - - - 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 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 FileSteeam(filename, FileMode.Open)) - { - using (var zip = Ionic.Zip.ZipFile.Read(inputStream)) - { - zip.AddEntry("Name1.txt", "this is the content"); - zip.Save(inputStream); // NO NO NO!! - } - } - - - - Better like this: - - - - using (var zip = Ionic.Zip.ZipFile.Read(filename)) - { - zip.AddEntry("Name1.txt", "this is the content"); - zip.Save(); // YES! - } - - - - - - The System.IO.Stream to write to. It must be - writable. If you created the ZipFile instanct by calling - ZipFile.Read(), this stream must not be the same stream - you passed to ZipFile.Read(). - - - - - 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. - - - - - - Saves the ZipFile instance to a self-extracting zip archive. - - - - - - The generated exe image will execute on any machine that has the .NET - Framework 2.0 installed on it. The generated exe image is also a - valid ZIP file, readable with DotNetZip or another Zip library or tool - such as WinZip. - - - - There are two "flavors" of self-extracting archive. The - WinFormsApplication version will pop up a GUI and allow the - user to select a target directory into which to extract. There's also - a checkbox allowing the user to specify to overwrite existing files, - and another checkbox to allow the user to request that Explorer be - opened to see the extracted files after extraction. The other flavor - is ConsoleApplication. A self-extractor generated with that - flavor setting will run from the command line. It accepts command-line - options to set the overwrite behavior, and to specify the target - extraction directory. - - - - There are a few temporary files created during the saving to a - self-extracting zip. These files are created in the directory pointed - to by , which defaults to . These temporary files are - removed upon successful completion of this method. - - - - When a user runs the WinForms SFX, the user's personal directory (Environment.SpecialFolder.Personal) - will be used as the default extract location. If you want to set the - default extract location, you should use the other overload of - SaveSelfExtractor()/ The user who runs the SFX will have the - opportunity to change the extract directory before extracting. When - the user runs the Command-Line SFX, the user must explicitly specify - the directory to which to extract. The .NET Framework 2.0 is required - on the computer when the self-extracting archive is run. - - - - NB: This method is not available in the version of DotNetZip build for - the .NET Compact Framework, nor in the "Reduced" DotNetZip library. - - - - - - - string DirectoryPath = "c:\\Documents\\Project7"; - using (ZipFile zip = new ZipFile()) - { - zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)); - zip.Comment = "This will be embedded into a self-extracting console-based exe"; - zip.SaveSelfExtractor("archive.exe", SelfExtractorFlavor.ConsoleApplication); - } - - - Dim DirectoryPath As String = "c:\Documents\Project7" - Using zip As New ZipFile() - zip.AddDirectory(DirectoryPath, System.IO.Path.GetFileName(DirectoryPath)) - zip.Comment = "This will be embedded into a self-extracting console-based exe" - zip.SaveSelfExtractor("archive.exe", SelfExtractorFlavor.ConsoleApplication) - End Using - - - - - a pathname, possibly fully qualified, to be created. Typically it - will end in an .exe extension. - - Indicates whether a Winforms or Console self-extractor is - desired. - - - - 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. - - - - 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. - - - - - 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. - - - - - 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 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. - - - - - The default text encoding used in zip archives. It is numeric 437, also - known as IBM437. - - - - - - 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. - - - - 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(). - - - - - - - - - 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. - - - - - - 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. - - - - - 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 - - - - - - - - - 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. - - - - - - - - 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. - - - - - - 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. - - - - - 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(). - - - - - 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. - - - - - 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 - - - - 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. - - - - - 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. - - - - - 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 - - - - Flush the stream. - - - - - 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. - - - - 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. - - - - - 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. - - - - - Compressor State - - - - 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. - - - - - 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. - - - - 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 - - - - The blocksize parameter specified at construction time. - - - - - 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. - - - - - 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. - - - - - Close the stream. - - - - This may or may not close the underlying stream. Check the - constructors that accept a bool value. - - - - - - Flush the stream. - - - - - 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. - - - - 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 - - - - 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. - - - - - - The blocksize parameter specified at construction time. - - - - - 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(). - - - - - Returns the "random" number at a specific index. - - the index - the random number - - - - 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. - - - - 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. - - - - - Flush 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 - - - - 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. - - - - 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. - - - - - 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. - - - - - 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 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(). - - - - - 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. - - - - 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. - - - - - Flush 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 - - - - 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 CRC on the GZIP stream. - - - This is used for internal error checking. You probably don't need to look at this property. - - - - - 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. - - - - 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. - - - - - 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. - - - - - 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. - - - - - 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); - } - } - } - } - - - - - - 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. - - - - - 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(). - - - - - 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. - - - - - - 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. - - - - - 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. - - - - The Adler32 checksum on the data transferred through the codec so far. You probably don't need to look at this. - - - - - 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. Defaults to 8192 bytes. - - - - - The minimum size of the working buffer used in the ZlibCodec class. Currently it is 128 bytes. - - - - - 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. - - - - - 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. - - - - - Flush 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 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. - - - - 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. - - - - - 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. - - - - - 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. - - - - - 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. - - - - - - Indicates the total number of bytes applied to the CRC. - - - - - Indicates the current CRC for all blocks slurped in. - - - - - 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 - - - - 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 - - - - Flush the stream. - - - - - 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. - - - - - 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 . - - - - - - Indicates whether the stream supports reading. - - - - - Indicates whether the stream supports seeking. - - - - Always returns false. - - - - - - Indicates whether the stream supports writing. - - - - - 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 - . - - - - diff --git a/HandsetDetectionAPIKit4/bin/Web.dll b/HandsetDetectionAPIKit4/bin/Web.dll deleted file mode 100644 index 80f70f7950a03c31dc0cb5dbaa9d938c99298f38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9728 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 - - - - - - - \ No newline at end of file diff --git a/HandsetDetectionAPIKit4/bin/nunit.framework.dll b/HandsetDetectionAPIKit4/bin/nunit.framework.dll deleted file mode 100644 index ed6550bb0556d716de525cd64e1a6cefb8a945bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 151552 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 - - - nunit.framework - - - - - The different targets a test action attribute can be applied to - - - - - Default target, which is determined by where the action attribute is attached - - - - - Target a individual test case - - - - - Target a suite of test cases - - - - - Delegate used by tests that execute code and - capture any thrown exception. - - - - - The Assert class contains a collection of static methods that - implement the most common assertions used in NUnit. - - - - - We don't actually want any instances of this object, but some people - like to inherit from it to add other static methods. Hence, the - protected constructor disallows any instances of this object. - - - - - The Equals method throws an AssertionException. This is done - to make sure there is no mistake by calling this function. - - - - - - - override the default ReferenceEquals to throw an AssertionException. This - implementation makes sure there is no mistake in calling this function - as part of Assert. - - - - - - - Throws a with the message and arguments - that are passed in. This allows a test to be cut short, with a result - of success returned to NUnit. - - The message to initialize the with. - Arguments to be used in formatting the message - - - - Throws a with the message and arguments - that are passed in. This allows a test to be cut short, with a result - of success returned to NUnit. - - The message to initialize the with. - - - - Throws a with the message and arguments - that are passed in. This allows a test to be cut short, with a result - of success returned to NUnit. - - - - - Throws an with the message and arguments - that are passed in. This is used by the other Assert functions. - - The message to initialize the with. - Arguments to be used in formatting the message - - - - Throws an with the message that is - passed in. This is used by the other Assert functions. - - The message to initialize the with. - - - - Throws an . - This is used by the other Assert functions. - - - - - Throws an with the message and arguments - that are passed in. This causes the test to be reported as ignored. - - The message to initialize the with. - Arguments to be used in formatting the message - - - - Throws an with the message that is - passed in. This causes the test to be reported as ignored. - - The message to initialize the with. - - - - Throws an . - This causes the test to be reported as ignored. - - - - - Throws an with the message and arguments - that are passed in. This causes the test to be reported as inconclusive. - - The message to initialize the with. - Arguments to be used in formatting the message - - - - Throws an with the message that is - passed in. This causes the test to be reported as inconclusive. - - The message to initialize the with. - - - - Throws an . - This causes the test to be reported as Inconclusive. - - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - The actual value to test - A Constraint to be applied - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - The actual value to test - A Constraint to be applied - The message that will be displayed on failure - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - The actual value to test - A Constraint expression to be applied - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display if the condition is false - Arguments to be used in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display if the condition is false - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - An ActualValueDelegate returning the value to be tested - A Constraint expression to be applied - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - An ActualValueDelegate returning the value to be tested - A Constraint expression to be applied - The message that will be displayed on failure - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - An ActualValueDelegate returning the value to be tested - A Constraint expression to be applied - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Apply a constraint to a referenced value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - The actual value to test - A Constraint to be applied - - - - Apply a constraint to a referenced value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - The actual value to test - A Constraint to be applied - The message that will be displayed on failure - - - - Apply a constraint to a referenced value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - The actual value to test - A Constraint to be applied - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that the code represented by a delegate throws an exception - that satisfies the constraint provided. - - A TestDelegate to be executed - A ThrowsConstraint used in the test - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - Used as a synonym for That in rare cases where a private setter - causes a Visual Basic compilation error. - - The actual value to test - A Constraint to be applied - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - Used as a synonym for That in rare cases where a private setter - causes a Visual Basic compilation error. - - The actual value to test - A Constraint to be applied - The message that will be displayed on failure - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - Used as a synonym for That in rare cases where a private setter - causes a Visual Basic compilation error. - - - This method is provided for use by VB developers needing to test - the value of properties with private setters. - - The actual value to test - A Constraint expression to be applied - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that a delegate throws a particular exception when called. - - A constraint to be satisfied by the exception - A TestDelegate - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that a delegate throws a particular exception when called. - - A constraint to be satisfied by the exception - A TestDelegate - The message that will be displayed on failure - - - - Verifies that a delegate throws a particular exception when called. - - A constraint to be satisfied by the exception - A TestDelegate - - - - Verifies that a delegate throws a particular exception when called. - - The exception Type expected - A TestDelegate - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that a delegate throws a particular exception when called. - - The exception Type expected - A TestDelegate - The message that will be displayed on failure - - - - Verifies that a delegate throws a particular exception when called. - - The exception Type expected - A TestDelegate - - - - Verifies that a delegate throws a particular exception when called. - - Type of the expected exception - A TestDelegate - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that a delegate throws a particular exception when called. - - Type of the expected exception - A TestDelegate - The message that will be displayed on failure - - - - Verifies that a delegate throws a particular exception when called. - - Type of the expected exception - A TestDelegate - - - - Verifies that a delegate throws an exception when called - and returns it. - - A TestDelegate - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that a delegate throws an exception when called - and returns it. - - A TestDelegate - The message that will be displayed on failure - - - - Verifies that a delegate throws an exception when called - and returns it. - - A TestDelegate - - - - Verifies that a delegate throws an exception of a certain Type - or one derived from it when called and returns it. - - The expected Exception Type - A TestDelegate - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that a delegate throws an exception of a certain Type - or one derived from it when called and returns it. - - The expected Exception Type - A TestDelegate - The message that will be displayed on failure - - - - Verifies that a delegate throws an exception of a certain Type - or one derived from it when called and returns it. - - The expected Exception Type - A TestDelegate - - - - Verifies that a delegate throws an exception of a certain Type - or one derived from it when called and returns it. - - The expected Exception Type - A TestDelegate - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that a delegate throws an exception of a certain Type - or one derived from it when called and returns it. - - The expected Exception Type - A TestDelegate - The message that will be displayed on failure - - - - Verifies that a delegate throws an exception of a certain Type - or one derived from it when called and returns it. - - The expected Exception Type - A TestDelegate - - - - Verifies that a delegate does not throw an exception - - A TestDelegate - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Verifies that a delegate does not throw an exception. - - A TestDelegate - The message that will be displayed on failure - - - - Verifies that a delegate does not throw an exception. - - A TestDelegate - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display in case of failure - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display in case of failure - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - - - - Asserts that a condition is false. If the condition is true the method throws - an . - - The evaluated condition - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that a condition is false. If the condition is true the method throws - an . - - The evaluated condition - The message to display in case of failure - - - - Asserts that a condition is false. If the condition is true the method throws - an . - - The evaluated condition - - - - Asserts that a condition is false. If the condition is true the method throws - an . - - The evaluated condition - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that a condition is false. If the condition is true the method throws - an . - - The evaluated condition - The message to display in case of failure - - - - Asserts that a condition is false. If the condition is true the method throws - an . - - The evaluated condition - - - - Verifies that the object that is passed in is not equal to null - If the object is null then an - is thrown. - - The object that is to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the object that is passed in is not equal to null - If the object is null then an - is thrown. - - The object that is to be tested - The message to display in case of failure - - - - Verifies that the object that is passed in is not equal to null - If the object is null then an - is thrown. - - The object that is to be tested - - - - Verifies that the object that is passed in is not equal to null - If the object is null then an - is thrown. - - The object that is to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the object that is passed in is not equal to null - If the object is null then an - is thrown. - - The object that is to be tested - The message to display in case of failure - - - - Verifies that the object that is passed in is not equal to null - If the object is null then an - is thrown. - - The object that is to be tested - - - - Verifies that the object that is passed in is equal to null - If the object is not null then an - is thrown. - - The object that is to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the object that is passed in is equal to null - If the object is not null then an - is thrown. - - The object that is to be tested - The message to display in case of failure - - - - Verifies that the object that is passed in is equal to null - If the object is not null then an - is thrown. - - The object that is to be tested - - - - Verifies that the object that is passed in is equal to null - If the object is not null then an - is thrown. - - The object that is to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the object that is passed in is equal to null - If the object is not null then an - is thrown. - - The object that is to be tested - The message to display in case of failure - - - - Verifies that the object that is passed in is equal to null - If the object is not null then an - is thrown. - - The object that is to be tested - - - - Verifies that two ints are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two ints are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two ints are equal. If they are not, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two longs are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two longs are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two longs are equal. If they are not, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two unsigned ints are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two unsigned ints are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two unsigned ints are equal. If they are not, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two unsigned longs are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two unsigned longs are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two unsigned longs are equal. If they are not, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two decimals are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two decimals are equal. If they are not, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two decimals are equal. If they are not, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two doubles are equal considering a delta. If the - expected value is infinity then the delta value is ignored. If - they are not equal then an is - thrown. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two doubles are equal considering a delta. If the - expected value is infinity then the delta value is ignored. If - they are not equal then an is - thrown. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - The message to display in case of failure - - - - Verifies that two doubles are equal considering a delta. If the - expected value is infinity then the delta value is ignored. If - they are not equal then an is - thrown. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - - - - Verifies that two doubles are equal considering a delta. If the - expected value is infinity then the delta value is ignored. If - they are not equal then an is - thrown. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two doubles are equal considering a delta. If the - expected value is infinity then the delta value is ignored. If - they are not equal then an is - thrown. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - The message to display in case of failure - - - - Verifies that two doubles are equal considering a delta. If the - expected value is infinity then the delta value is ignored. If - they are not equal then an is - thrown. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - - - - Verifies that two objects are equal. Two objects are considered - equal if both are null, or if both have the same value. NUnit - has special semantics for some object types. - If they are not equal an is thrown. - - The value that is expected - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two objects are equal. Two objects are considered - equal if both are null, or if both have the same value. NUnit - has special semantics for some object types. - If they are not equal an is thrown. - - The value that is expected - The actual value - The message to display in case of failure - - - - Verifies that two objects are equal. Two objects are considered - equal if both are null, or if both have the same value. NUnit - has special semantics for some object types. - If they are not equal an is thrown. - - The value that is expected - The actual value - - - - Verifies that two ints are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two ints are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two ints are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two longs are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two longs are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two longs are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two unsigned ints are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two unsigned ints are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two unsigned ints are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two unsigned longs are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two unsigned longs are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two unsigned longs are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two decimals are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two decimals are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two decimals are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two floats are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two floats are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two floats are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two doubles are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two doubles are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - The message to display in case of failure - - - - Verifies that two doubles are not equal. If they are equal, then an - is thrown. - - The expected value - The actual value - - - - Verifies that two objects are not equal. Two objects are considered - equal if both are null, or if both have the same value. NUnit - has special semantics for some object types. - If they are equal an is thrown. - - The value that is expected - The actual value - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that two objects are not equal. Two objects are considered - equal if both are null, or if both have the same value. NUnit - has special semantics for some object types. - If they are equal an is thrown. - - The value that is expected - The actual value - The message to display in case of failure - - - - Verifies that two objects are not equal. Two objects are considered - equal if both are null, or if both have the same value. NUnit - has special semantics for some object types. - If they are equal an is thrown. - - The value that is expected - The actual value - - - - Asserts that two objects refer to the same object. If they - are not the same an is thrown. - - The expected object - The actual object - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that two objects refer to the same object. If they - are not the same an is thrown. - - The expected object - The actual object - The message to display in case of failure - - - - Asserts that two objects refer to the same object. If they - are not the same an is thrown. - - The expected object - The actual object - - - - Asserts that two objects do not refer to the same object. If they - are the same an is thrown. - - The expected object - The actual object - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that two objects do not refer to the same object. If they - are the same an is thrown. - - The expected object - The actual object - The message to display in case of failure - - - - Asserts that two objects do not refer to the same object. If they - are the same an is thrown. - - The expected object - The actual object - - - - Verifies that the double that is passed in is an NaN value. - If the object is not NaN then an - is thrown. - - The value that is to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the double that is passed in is an NaN value. - If the object is not NaN then an - is thrown. - - The value that is to be tested - The message to display in case of failure - - - - Verifies that the double that is passed in is an NaN value. - If the object is not NaN then an - is thrown. - - The value that is to be tested - - - - Verifies that the double that is passed in is an NaN value. - If the object is not NaN then an - is thrown. - - The value that is to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the double that is passed in is an NaN value. - If the object is not NaN then an - is thrown. - - The value that is to be tested - The message to display in case of failure - - - - Verifies that the double that is passed in is an NaN value. - If the object is not NaN then an - is thrown. - - The value that is to be tested - - - - Assert that a string is empty - that is equal to string.Empty - - The string to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Assert that a string is empty - that is equal to string.Empty - - The string to be tested - The message to display in case of failure - - - - Assert that a string is empty - that is equal to string.Empty - - The string to be tested - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing ICollection - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing ICollection - The message to display in case of failure - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing ICollection - - - - Assert that a string is not empty - that is not equal to string.Empty - - The string to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Assert that a string is not empty - that is not equal to string.Empty - - The string to be tested - The message to display in case of failure - - - - Assert that a string is not empty - that is not equal to string.Empty - - The string to be tested - - - - Assert that an array, list or other collection is not empty - - An array, list or other collection implementing ICollection - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Assert that an array, list or other collection is not empty - - An array, list or other collection implementing ICollection - The message to display in case of failure - - - - Assert that an array, list or other collection is not empty - - An array, list or other collection implementing ICollection - - - - Assert that a string is either null or equal to string.Empty - - The string to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Assert that a string is either null or equal to string.Empty - - The string to be tested - The message to display in case of failure - - - - Assert that a string is either null or equal to string.Empty - - The string to be tested - - - - Assert that a string is not null or empty - - The string to be tested - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Assert that a string is not null or empty - - The string to be tested - The message to display in case of failure - - - - Assert that a string is not null or empty - - The string to be tested - - - - Asserts that an object may be assigned a value of a given Type. - - The expected Type. - The object under examination - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object may be assigned a value of a given Type. - - The expected Type. - The object under examination - The message to display in case of failure - - - - Asserts that an object may be assigned a value of a given Type. - - The expected Type. - The object under examination - - - - Asserts that an object may be assigned a value of a given Type. - - The expected Type. - The object under examination - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object may be assigned a value of a given Type. - - The expected Type. - The object under examination - The message to display in case of failure - - - - Asserts that an object may be assigned a value of a given Type. - - The expected Type. - The object under examination - - - - Asserts that an object may not be assigned a value of a given Type. - - The expected Type. - The object under examination - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object may not be assigned a value of a given Type. - - The expected Type. - The object under examination - The message to display in case of failure - - - - Asserts that an object may not be assigned a value of a given Type. - - The expected Type. - The object under examination - - - - Asserts that an object may not be assigned a value of a given Type. - - The expected Type. - The object under examination - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object may not be assigned a value of a given Type. - - The expected Type. - The object under examination - The message to display in case of failure - - - - Asserts that an object may not be assigned a value of a given Type. - - The expected Type. - The object under examination - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - - - - Asserts that an object is an instance of a given type. - - The expected Type - The object being examined - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - The message to display in case of failure - - - - Asserts that an object is not an instance of a given type. - - The expected Type - The object being examined - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than the second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - The message to display in case of failure - - - - Verifies that the first value is greater than or equal tothe second - value. If it is not, then an - is thrown. - - The first value, expected to be greater - The second value, expected to be less - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - The message to display in case of failure - - - - Verifies that the first value is less than or equal to the second - value. If it is not, then an - is thrown. - - The first value, expected to be less - The second value, expected to be greater - - - - Asserts that an object is contained in a list. - - The expected object - The list to be examined - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Asserts that an object is contained in a list. - - The expected object - The list to be examined - The message to display in case of failure - - - - Asserts that an object is contained in a list. - - The expected object - The list to be examined - - - - Helper for Assert.AreEqual(double expected, double actual, ...) - allowing code generation to work consistently. - - The expected value - The actual value - The maximum acceptable difference between the - the expected and the actual - The message to display in case of failure - Array of objects to be used in formatting the message - - - - Gets the number of assertions executed so far and - resets the counter to zero. - - - - - AssertionHelper is an optional base class for user tests, - allowing the use of shorter names for constraints and - asserts and avoiding conflict with the definition of - , from which it inherits much of its - behavior, in certain mock object frameworks. - - - - - Helper class with properties and methods that supply - a number of constraints used in Asserts. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding only if a specified number of them succeed. - - - - - Returns a new PropertyConstraintExpression, which will either - test for the existence of the named property on the object - being tested or apply any following constraint to that property. - - - - - Returns a new AttributeConstraint checking for the - presence of a particular attribute on an object. - - - - - Returns a new AttributeConstraint checking for the - presence of a particular attribute on an object. - - - - - Returns a constraint that tests two items for equality - - - - - Returns a constraint that tests that two references are the same object - - - - - Returns a constraint that tests whether the - actual value is greater than the suppled argument - - - - - Returns a constraint that tests whether the - actual value is greater than or equal to the suppled argument - - - - - Returns a constraint that tests whether the - actual value is greater than or equal to the suppled argument - - - - - Returns a constraint that tests whether the - actual value is less than the suppled argument - - - - - Returns a constraint that tests whether the - actual value is less than or equal to the suppled argument - - - - - Returns a constraint that tests whether the - actual value is less than or equal to the suppled argument - - - - - Returns a constraint that tests whether the actual - value is of the exact type supplied as an argument. - - - - - Returns a constraint that tests whether the actual - value is of the exact type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is a collection containing the same elements as the - collection supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is a subset of the collection supplied as an argument. - - - - - Returns a new CollectionContainsConstraint checking for the - presence of a particular object in the collection. - - - - - Returns a new CollectionContainsConstraint checking for the - presence of a particular object in the collection. - - - - - Returns a new ContainsConstraint. This constraint - will, in turn, make use of the appropriate second-level - constraint, depending on the type of the actual argument. - This overload is only used if the item sought is a string, - since any other type implies that we are looking for a - collection member. - - - - - Returns a constraint that succeeds if the actual - value contains the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value contains the substring supplied as an argument. - - - - - Returns a constraint that fails if the actual - value contains the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value starts with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value starts with the substring supplied as an argument. - - - - - Returns a constraint that fails if the actual - value starts with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value ends with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value ends with the substring supplied as an argument. - - - - - Returns a constraint that fails if the actual - value ends with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value matches the regular expression supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value matches the regular expression supplied as an argument. - - - - - Returns a constraint that fails if the actual - value matches the pattern supplied as an argument. - - - - - Returns a constraint that tests whether the path provided - is the same as an expected path after canonicalization. - - - - - Returns a constraint that tests whether the path provided - is the same path or under an expected path after canonicalization. - - - - - Returns a constraint that tests whether the path provided - is the same path or under an expected path after canonicalization. - - - - - Returns a constraint that tests whether the actual value falls - within a specified range. - - - - - Returns a ConstraintExpression that negates any - following constraint. - - - - - Returns a ConstraintExpression that negates any - following constraint. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if all of them succeed. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if at least one of them succeeds. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if all of them fail. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the Length property of the object being tested. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the Count property of the object being tested. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the Message property of the object being tested. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the InnerException property of the object being tested. - - - - - Returns a constraint that tests for null - - - - - Returns a constraint that tests for True - - - - - Returns a constraint that tests for False - - - - - Returns a constraint that tests for a positive value - - - - - Returns a constraint that tests for a negative value - - - - - Returns a constraint that tests for NaN - - - - - Returns a constraint that tests for empty - - - - - Returns a constraint that tests whether a collection - contains all unique items. - - - - - Returns a constraint that tests whether an object graph is serializable in binary format. - - - - - Returns a constraint that tests whether an object graph is serializable in xml format. - - - - - Returns a constraint that tests whether a collection is ordered - - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. Works - identically to Assert.That. - - The actual value to test - A Constraint to be applied - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. Works - identically to Assert.That. - - The actual value to test - A Constraint to be applied - The message to be displayed in case of failure - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. Works - identically to Assert.That. - - The actual value to test - A Constraint to be applied - The message to be displayed in case of failure - Arguments to use in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . Works Identically to - . - - The evaluated condition - The message to display if the condition is false - Arguments to be used in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . Works Identically to - . - - The evaluated condition - The message to display if the condition is false - - - - Asserts that a condition is true. If the condition is false the method throws - an . Works Identically to . - - The evaluated condition - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - A Constraint expression to be applied - An ActualValueDelegate returning the value to be tested - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - A Constraint expression to be applied - An ActualValueDelegate returning the value to be tested - The message that will be displayed on failure - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - An ActualValueDelegate returning the value to be tested - A Constraint expression to be applied - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Apply a constraint to a referenced value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - The actual value to test - A Constraint to be applied - - - - Apply a constraint to a referenced value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - The actual value to test - A Constraint to be applied - The message that will be displayed on failure - - - - Apply a constraint to a referenced value, succeeding if the constraint - is satisfied and throwing an assertion exception on failure. - - The actual value to test - A Constraint to be applied - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that the code represented by a delegate throws an exception - that satisfies the constraint provided. - - A TestDelegate to be executed - A ThrowsConstraint used in the test - - - - Returns a ListMapper based on a collection. - - The original collection - - - - - Provides static methods to express the assumptions - that must be met for a test to give a meaningful - result. If an assumption is not met, the test - should produce an inconclusive result. - - - - - The Equals method throws an AssertionException. This is done - to make sure there is no mistake by calling this function. - - - - - - - override the default ReferenceEquals to throw an AssertionException. This - implementation makes sure there is no mistake in calling this function - as part of Assert. - - - - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an InconclusiveException on failure. - - A Constraint expression to be applied - The actual value to test - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an InconclusiveException on failure. - - A Constraint expression to be applied - The actual value to test - The message that will be displayed on failure - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an InconclusiveException on failure. - - A Constraint expression to be applied - The actual value to test - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display if the condition is false - Arguments to be used in formatting the message - - - - Asserts that a condition is true. If the condition is false the method throws - an . - - The evaluated condition - The message to display if the condition is false - - - - Asserts that a condition is true. If the condition is false the - method throws an . - - The evaluated condition - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an InconclusiveException on failure. - - A Constraint expression to be applied - An ActualValueDelegate returning the value to be tested - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an InconclusiveException on failure. - - A Constraint expression to be applied - An ActualValueDelegate returning the value to be tested - The message that will be displayed on failure - - - - Apply a constraint to an actual value, succeeding if the constraint - is satisfied and throwing an InconclusiveException on failure. - - An ActualValueDelegate returning the value to be tested - A Constraint expression to be applied - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Apply a constraint to a referenced value, succeeding if the constraint - is satisfied and throwing an InconclusiveException on failure. - - A Constraint expression to be applied - The actual value to test - - - - Apply a constraint to a referenced value, succeeding if the constraint - is satisfied and throwing an InconclusiveException on failure. - - A Constraint expression to be applied - The actual value to test - The message that will be displayed on failure - - - - Apply a constraint to a referenced value, succeeding if the constraint - is satisfied and throwing an InconclusiveException on failure. - - A Constraint expression to be applied - The actual value to test - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that the code represented by a delegate throws an exception - that satisfies the constraint provided. - - A TestDelegate to be executed - A ThrowsConstraint used in the test - - - - Waits for pending asynchronous operations to complete, if appropriate, - and returns a proper result of the invocation by unwrapping task results - - The raw result of the method invocation - The unwrapped result, if necessary - - - - A set of Assert methods operationg on one or more collections - - - - - The Equals method throws an AssertionException. This is done - to make sure there is no mistake by calling this function. - - - - - - - override the default ReferenceEquals to throw an AssertionException. This - implementation makes sure there is no mistake in calling this function - as part of Assert. - - - - - - - Asserts that all items contained in collection are of the type specified by expectedType. - - IEnumerable containing objects to be considered - System.Type that all objects in collection must be instances of - - - - Asserts that all items contained in collection are of the type specified by expectedType. - - IEnumerable containing objects to be considered - System.Type that all objects in collection must be instances of - The message that will be displayed on failure - - - - Asserts that all items contained in collection are of the type specified by expectedType. - - IEnumerable containing objects to be considered - System.Type that all objects in collection must be instances of - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that all items contained in collection are not equal to null. - - IEnumerable containing objects to be considered - - - - Asserts that all items contained in collection are not equal to null. - - IEnumerable containing objects to be considered - The message that will be displayed on failure - - - - Asserts that all items contained in collection are not equal to null. - - IEnumerable of objects to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Ensures that every object contained in collection exists within the collection - once and only once. - - IEnumerable of objects to be considered - - - - Ensures that every object contained in collection exists within the collection - once and only once. - - IEnumerable of objects to be considered - The message that will be displayed on failure - - - - Ensures that every object contained in collection exists within the collection - once and only once. - - IEnumerable of objects to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that expected and actual are exactly equal. The collections must have the same count, - and contain the exact same objects in the same order. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - - - - Asserts that expected and actual are exactly equal. The collections must have the same count, - and contain the exact same objects in the same order. - If comparer is not null then it will be used to compare the objects. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The IComparer to use in comparing objects from each IEnumerable - - - - Asserts that expected and actual are exactly equal. The collections must have the same count, - and contain the exact same objects in the same order. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - - - - Asserts that expected and actual are exactly equal. The collections must have the same count, - and contain the exact same objects in the same order. - If comparer is not null then it will be used to compare the objects. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The IComparer to use in comparing objects from each IEnumerable - The message that will be displayed on failure - - - - Asserts that expected and actual are exactly equal. The collections must have the same count, - and contain the exact same objects in the same order. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that expected and actual are exactly equal. The collections must have the same count, - and contain the exact same objects in the same order. - If comparer is not null then it will be used to compare the objects. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The IComparer to use in comparing objects from each IEnumerable - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - - - - Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - - - - Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that expected and actual are not exactly equal. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - - - - Asserts that expected and actual are not exactly equal. - If comparer is not null then it will be used to compare the objects. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The IComparer to use in comparing objects from each IEnumerable - - - - Asserts that expected and actual are not exactly equal. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - - - - Asserts that expected and actual are not exactly equal. - If comparer is not null then it will be used to compare the objects. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The IComparer to use in comparing objects from each IEnumerable - The message that will be displayed on failure - - - - Asserts that expected and actual are not exactly equal. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that expected and actual are not exactly equal. - If comparer is not null then it will be used to compare the objects. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The IComparer to use in comparing objects from each IEnumerable - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that expected and actual are not equivalent. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - - - - Asserts that expected and actual are not equivalent. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - - - - Asserts that expected and actual are not equivalent. - - The first IEnumerable of objects to be considered - The second IEnumerable of objects to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that collection contains actual as an item. - - IEnumerable of objects to be considered - Object to be found within collection - - - - Asserts that collection contains actual as an item. - - IEnumerable of objects to be considered - Object to be found within collection - The message that will be displayed on failure - - - - Asserts that collection contains actual as an item. - - IEnumerable of objects to be considered - Object to be found within collection - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that collection does not contain actual as an item. - - IEnumerable of objects to be considered - Object that cannot exist within collection - - - - Asserts that collection does not contain actual as an item. - - IEnumerable of objects to be considered - Object that cannot exist within collection - The message that will be displayed on failure - - - - Asserts that collection does not contain actual as an item. - - IEnumerable of objects to be considered - Object that cannot exist within collection - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that the superset does not contain the subset - - The IEnumerable subset to be considered - The IEnumerable superset to be considered - - - - Asserts that the superset does not contain the subset - - The IEnumerable subset to be considered - The IEnumerable superset to be considered - The message that will be displayed on failure - - - - Asserts that the superset does not contain the subset - - The IEnumerable subset to be considered - The IEnumerable superset to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Asserts that the superset contains the subset. - - The IEnumerable subset to be considered - The IEnumerable superset to be considered - - - - Asserts that the superset contains the subset. - - The IEnumerable subset to be considered - The IEnumerable superset to be considered - The message that will be displayed on failure - - - - Asserts that the superset contains the subset. - - The IEnumerable subset to be considered - The IEnumerable superset to be considered - The message that will be displayed on failure - Arguments to be used in formatting the message - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing IEnumerable - The message to be displayed on failure - Arguments to be used in formatting the message - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing IEnumerable - The message to be displayed on failure - - - - Assert that an array,list or other collection is empty - - An array, list or other collection implementing IEnumerable - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing IEnumerable - The message to be displayed on failure - Arguments to be used in formatting the message - - - - Assert that an array, list or other collection is empty - - An array, list or other collection implementing IEnumerable - The message to be displayed on failure - - - - Assert that an array,list or other collection is empty - - An array, list or other collection implementing IEnumerable - - - - Assert that an array, list or other collection is ordered - - An array, list or other collection implementing IEnumerable - The message to be displayed on failure - Arguments to be used in formatting the message - - - - Assert that an array, list or other collection is ordered - - An array, list or other collection implementing IEnumerable - The message to be displayed on failure - - - - Assert that an array, list or other collection is ordered - - An array, list or other collection implementing IEnumerable - - - - Assert that an array, list or other collection is ordered - - An array, list or other collection implementing IEnumerable - A custom comparer to perform the comparisons - The message to be displayed on failure - Arguments to be used in formatting the message - - - - Assert that an array, list or other collection is ordered - - An array, list or other collection implementing IEnumerable - A custom comparer to perform the comparisons - The message to be displayed on failure - - - - Assert that an array, list or other collection is ordered - - An array, list or other collection implementing IEnumerable - A custom comparer to perform the comparisons - - - - Helper class with properties and methods that supply - a number of constraints used in Asserts. - - - - - Returns a new CollectionContainsConstraint checking for the - presence of a particular object in the collection. - - - - - Returns a constraint that succeeds if the actual - value contains the substring supplied as an argument. - - - - - Summary description for DirectoryAssert - - - - - The Equals method throws an AssertionException. This is done - to make sure there is no mistake by calling this function. - - - - - - - override the default ReferenceEquals to throw an AssertionException. This - implementation makes sure there is no mistake in calling this function - as part of Assert. - - - - - - - We don't actually want any instances of this object, but some people - like to inherit from it to add other static methods. Hence, the - protected constructor disallows any instances of this object. - - - - - Verifies that two directories are equal. Two directories are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A directory containing the value that is expected - A directory containing the actual value - The message to display if directories are not equal - Arguments to be used in formatting the message - - - - Verifies that two directories are equal. Two directories are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A directory containing the value that is expected - A directory containing the actual value - The message to display if directories are not equal - - - - Verifies that two directories are equal. Two directories are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A directory containing the value that is expected - A directory containing the actual value - - - - Verifies that two directories are equal. Two directories are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A directory path string containing the value that is expected - A directory path string containing the actual value - The message to display if directories are not equal - Arguments to be used in formatting the message - - - - Verifies that two directories are equal. Two directories are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A directory path string containing the value that is expected - A directory path string containing the actual value - The message to display if directories are not equal - - - - Verifies that two directories are equal. Two directories are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A directory path string containing the value that is expected - A directory path string containing the actual value - - - - Asserts that two directories are not equal. If they are equal - an is thrown. - - A directory containing the value that is expected - A directory containing the actual value - The message to display if directories are not equal - Arguments to be used in formatting the message - - - - Asserts that two directories are not equal. If they are equal - an is thrown. - - A directory containing the value that is expected - A directory containing the actual value - The message to display if directories are not equal - - - - Asserts that two directories are not equal. If they are equal - an is thrown. - - A directory containing the value that is expected - A directory containing the actual value - - - - Asserts that two directories are not equal. If they are equal - an is thrown. - - A directory path string containing the value that is expected - A directory path string containing the actual value - The message to display if directories are equal - Arguments to be used in formatting the message - - - - Asserts that two directories are not equal. If they are equal - an is thrown. - - A directory path string containing the value that is expected - A directory path string containing the actual value - The message to display if directories are equal - - - - Asserts that two directories are not equal. If they are equal - an is thrown. - - A directory path string containing the value that is expected - A directory path string containing the actual value - - - - Asserts that the directory is empty. If it is not empty - an is thrown. - - A directory to search - The message to display if directories are not equal - Arguments to be used in formatting the message - - - - Asserts that the directory is empty. If it is not empty - an is thrown. - - A directory to search - The message to display if directories are not equal - - - - Asserts that the directory is empty. If it is not empty - an is thrown. - - A directory to search - - - - Asserts that the directory is empty. If it is not empty - an is thrown. - - A directory to search - The message to display if directories are not equal - Arguments to be used in formatting the message - - - - Asserts that the directory is empty. If it is not empty - an is thrown. - - A directory to search - The message to display if directories are not equal - - - - Asserts that the directory is empty. If it is not empty - an is thrown. - - A directory to search - - - - Asserts that the directory is not empty. If it is empty - an is thrown. - - A directory to search - The message to display if directories are not equal - Arguments to be used in formatting the message - - - - Asserts that the directory is not empty. If it is empty - an is thrown. - - A directory to search - The message to display if directories are not equal - - - - Asserts that the directory is not empty. If it is empty - an is thrown. - - A directory to search - - - - Asserts that the directory is not empty. If it is empty - an is thrown. - - A directory to search - The message to display if directories are not equal - Arguments to be used in formatting the message - - - - Asserts that the directory is not empty. If it is empty - an is thrown. - - A directory to search - The message to display if directories are not equal - - - - Asserts that the directory is not empty. If it is empty - an is thrown. - - A directory to search - - - - Asserts that path contains actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - The message to display if directory is not within the path - Arguments to be used in formatting the message - - - - Asserts that path contains actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - The message to display if directory is not within the path - - - - Asserts that path contains actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - - - - Asserts that path contains actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - The message to display if directory is not within the path - Arguments to be used in formatting the message - - - - Asserts that path contains actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - The message to display if directory is not within the path - - - - Asserts that path contains actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - - - - Asserts that path does not contain actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - The message to display if directory is not within the path - Arguments to be used in formatting the message - - - - Asserts that path does not contain actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - The message to display if directory is not within the path - - - - Asserts that path does not contain actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - - - - Asserts that path does not contain actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - The message to display if directory is not within the path - Arguments to be used in formatting the message - - - - Asserts that path does not contain actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - The message to display if directory is not within the path - - - - Asserts that path does not contain actual as a subdirectory or - an is thrown. - - A directory to search - sub-directory asserted to exist under directory - - - - Summary description for FileAssert. - - - - - The Equals method throws an AssertionException. This is done - to make sure there is no mistake by calling this function. - - - - - - - override the default ReferenceEquals to throw an AssertionException. This - implementation makes sure there is no mistake in calling this function - as part of Assert. - - - - - - - We don't actually want any instances of this object, but some people - like to inherit from it to add other static methods. Hence, the - protected constructor disallows any instances of this object. - - - - - Verifies that two Streams are equal. Two Streams are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - The expected Stream - The actual Stream - The message to display if Streams are not equal - Arguments to be used in formatting the message - - - - Verifies that two Streams are equal. Two Streams are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - The expected Stream - The actual Stream - The message to display if objects are not equal - - - - Verifies that two Streams are equal. Two Streams are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - The expected Stream - The actual Stream - - - - Verifies that two files are equal. Two files are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A file containing the value that is expected - A file containing the actual value - The message to display if Streams are not equal - Arguments to be used in formatting the message - - - - Verifies that two files are equal. Two files are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A file containing the value that is expected - A file containing the actual value - The message to display if objects are not equal - - - - Verifies that two files are equal. Two files are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - A file containing the value that is expected - A file containing the actual value - - - - Verifies that two files are equal. Two files are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - The path to a file containing the value that is expected - The path to a file containing the actual value - The message to display if Streams are not equal - Arguments to be used in formatting the message - - - - Verifies that two files are equal. Two files are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - The path to a file containing the value that is expected - The path to a file containing the actual value - The message to display if objects are not equal - - - - Verifies that two files are equal. Two files are considered - equal if both are null, or if both have the same value byte for byte. - If they are not equal an is thrown. - - The path to a file containing the value that is expected - The path to a file containing the actual value - - - - Asserts that two Streams are not equal. If they are equal - an is thrown. - - The expected Stream - The actual Stream - The message to be displayed when the two Stream are the same. - Arguments to be used in formatting the message - - - - Asserts that two Streams are not equal. If they are equal - an is thrown. - - The expected Stream - The actual Stream - The message to be displayed when the Streams are the same. - - - - Asserts that two Streams are not equal. If they are equal - an is thrown. - - The expected Stream - The actual Stream - - - - Asserts that two files are not equal. If they are equal - an is thrown. - - A file containing the value that is expected - A file containing the actual value - The message to display if Streams are not equal - Arguments to be used in formatting the message - - - - Asserts that two files are not equal. If they are equal - an is thrown. - - A file containing the value that is expected - A file containing the actual value - The message to display if objects are not equal - - - - Asserts that two files are not equal. If they are equal - an is thrown. - - A file containing the value that is expected - A file containing the actual value - - - - Asserts that two files are not equal. If they are equal - an is thrown. - - The path to a file containing the value that is expected - The path to a file containing the actual value - The message to display if Streams are not equal - Arguments to be used in formatting the message - - - - Asserts that two files are not equal. If they are equal - an is thrown. - - The path to a file containing the value that is expected - The path to a file containing the actual value - The message to display if objects are not equal - - - - Asserts that two files are not equal. If they are equal - an is thrown. - - The path to a file containing the value that is expected - The path to a file containing the actual value - - - - GlobalSettings is a place for setting default values used - by the framework in performing asserts. - - - - - Default tolerance for floating point equality - - - - - Class used to guard against unexpected argument values - by throwing an appropriate exception. - - - - - Throws an exception if an argument is null - - The value to be tested - The name of the argument - - - - Throws an exception if a string argument is null or empty - - The value to be tested - The name of the argument - - - - Helper class with properties and methods that supply - a number of constraints used in Asserts. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding only if a specified number of them succeed. - - - - - Returns a new PropertyConstraintExpression, which will either - test for the existence of the named property on the object - being tested or apply any following constraint to that property. - - - - - Returns a new AttributeConstraint checking for the - presence of a particular attribute on an object. - - - - - Returns a new AttributeConstraint checking for the - presence of a particular attribute on an object. - - - - - Returns a new CollectionContainsConstraint checking for the - presence of a particular object in the collection. - - - - - Returns a ConstraintExpression that negates any - following constraint. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if all of them succeed. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if at least one of them succeeds. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if all of them fail. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the Length property of the object being tested. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the Count property of the object being tested. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the Message property of the object being tested. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the InnerException property of the object being tested. - - - - - Interface implemented by a user fixture in order to - validate any expected exceptions. It is only called - for test methods marked with the ExpectedException - attribute. - - - - - Method to handle an expected exception - - The exception to be handled - - - - Helper class with properties and methods that supply - a number of constraints used in Asserts. - - - - - Returns a constraint that tests two items for equality - - - - - Returns a constraint that tests that two references are the same object - - - - - Returns a constraint that tests whether the - actual value is greater than the suppled argument - - - - - Returns a constraint that tests whether the - actual value is greater than or equal to the suppled argument - - - - - Returns a constraint that tests whether the - actual value is greater than or equal to the suppled argument - - - - - Returns a constraint that tests whether the - actual value is less than the suppled argument - - - - - Returns a constraint that tests whether the - actual value is less than or equal to the suppled argument - - - - - Returns a constraint that tests whether the - actual value is less than or equal to the suppled argument - - - - - Returns a constraint that tests whether the actual - value is of the exact type supplied as an argument. - - - - - Returns a constraint that tests whether the actual - value is of the exact type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is a collection containing the same elements as the - collection supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is a subset of the collection supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value contains the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value starts with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value ends with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value matches the regular expression supplied as an argument. - - - - - Returns a constraint that tests whether the path provided - is the same as an expected path after canonicalization. - - - - - Returns a constraint that tests whether the path provided - is under an expected path after canonicalization. - - - - - Returns a constraint that tests whether the path provided - is the same path or under an expected path after canonicalization. - - - - - Returns a constraint that tests whether the actual value falls - within a specified range. - - - - - Returns a ConstraintExpression that negates any - following constraint. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if all of them succeed. - - - - - Returns a constraint that tests for null - - - - - Returns a constraint that tests for True - - - - - Returns a constraint that tests for False - - - - - Returns a constraint that tests for a positive value - - - - - Returns a constraint that tests for a negative value - - - - - Returns a constraint that tests for NaN - - - - - Returns a constraint that tests for empty - - - - - Returns a constraint that tests whether a collection - contains all unique items. - - - - - Returns a constraint that tests whether an object graph is serializable in binary format. - - - - - Returns a constraint that tests whether an object graph is serializable in xml format. - - - - - Returns a constraint that tests whether a collection is ordered - - - - - The ITestCaseData interface is implemented by a class - that is able to return complete testcases for use by - a parameterized test method. - - NOTE: This interface is used in both the framework - and the core, even though that results in two different - types. However, sharing the source code guarantees that - the various implementations will be compatible and that - the core is able to reflect successfully over the - framework implementations of ITestCaseData. - - - - - Gets the argument list to be provided to the test - - - - - Gets the expected result - - - - - Indicates whether a result has been specified. - This is necessary because the result may be - null, so it's value cannot be checked. - - - - - Gets the expected exception Type - - - - - Gets the FullName of the expected exception - - - - - Gets the name to be used for the test - - - - - Gets the description of the test - - - - - Gets a value indicating whether this is ignored. - - true if ignored; otherwise, false. - - - - Gets a value indicating whether this is explicit. - - true if explicit; otherwise, false. - - - - Gets the ignore reason. - - The ignore reason. - - - - The Iz class is a synonym for Is intended for use in VB, - which regards Is as a keyword. - - - - - The List class is a helper class with properties and methods - that supply a number of constraints used with lists and collections. - - - - - List.Map returns a ListMapper, which can be used to map - the original collection to another collection. - - - - - - - ListMapper is used to transform a collection used as an actual argument - producing another collection to be used in the assertion. - - - - - Construct a ListMapper based on a collection - - The collection to be transformed - - - - Produces a collection containing all the values of a property - - The collection of property values - - - - - Randomizer returns a set of random values in a repeatable - way, to allow re-running of tests if necessary. - - - - - Get a randomizer for a particular member, returning - one that has already been created if it exists. - This ensures that the same values are generated - each time the tests are reloaded. - - - - - Get a randomizer for a particular parameter, returning - one that has already been created if it exists. - This ensures that the same values are generated - each time the tests are reloaded. - - - - - Construct a randomizer using a random seed - - - - - Construct a randomizer using a specified seed - - - - - Return an array of random doubles between 0.0 and 1.0. - - - - - - - Return an array of random doubles with values in a specified range. - - - - - Return an array of random ints with values in a specified range. - - - - - Get a random seed for use in creating a randomizer. - - - - - The SpecialValue enum is used to represent TestCase arguments - that cannot be used as arguments to an Attribute. - - - - - Null represents a null value, which cannot be used as an - argument to an attribute under .NET 1.x - - - - - Basic Asserts on strings. - - - - - The Equals method throws an AssertionException. This is done - to make sure there is no mistake by calling this function. - - - - - - - override the default ReferenceEquals to throw an AssertionException. This - implementation makes sure there is no mistake in calling this function - as part of Assert. - - - - - - - Asserts that a string is found within another string. - - The expected string - The string to be examined - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string is found within another string. - - The expected string - The string to be examined - The message to display in case of failure - - - - Asserts that a string is found within another string. - - The expected string - The string to be examined - - - - Asserts that a string is not found within another string. - - The expected string - The string to be examined - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string is found within another string. - - The expected string - The string to be examined - The message to display in case of failure - - - - Asserts that a string is found within another string. - - The expected string - The string to be examined - - - - Asserts that a string starts with another string. - - The expected string - The string to be examined - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string starts with another string. - - The expected string - The string to be examined - The message to display in case of failure - - - - Asserts that a string starts with another string. - - The expected string - The string to be examined - - - - Asserts that a string does not start with another string. - - The expected string - The string to be examined - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string does not start with another string. - - The expected string - The string to be examined - The message to display in case of failure - - - - Asserts that a string does not start with another string. - - The expected string - The string to be examined - - - - Asserts that a string ends with another string. - - The expected string - The string to be examined - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string ends with another string. - - The expected string - The string to be examined - The message to display in case of failure - - - - Asserts that a string ends with another string. - - The expected string - The string to be examined - - - - Asserts that a string does not end with another string. - - The expected string - The string to be examined - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string does not end with another string. - - The expected string - The string to be examined - The message to display in case of failure - - - - Asserts that a string does not end with another string. - - The expected string - The string to be examined - - - - Asserts that two strings are equal, without regard to case. - - The expected string - The actual string - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that two strings are equal, without regard to case. - - The expected string - The actual string - The message to display in case of failure - - - - Asserts that two strings are equal, without regard to case. - - The expected string - The actual string - - - - Asserts that two strings are not equal, without regard to case. - - The expected string - The actual string - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that two strings are Notequal, without regard to case. - - The expected string - The actual string - The message to display in case of failure - - - - Asserts that two strings are not equal, without regard to case. - - The expected string - The actual string - - - - Asserts that a string matches an expected regular expression pattern. - - The regex pattern to be matched - The actual string - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string matches an expected regular expression pattern. - - The regex pattern to be matched - The actual string - The message to display in case of failure - - - - Asserts that a string matches an expected regular expression pattern. - - The regex pattern to be matched - The actual string - - - - Asserts that a string does not match an expected regular expression pattern. - - The regex pattern to be used - The actual string - The message to display in case of failure - Arguments used in formatting the message - - - - Asserts that a string does not match an expected regular expression pattern. - - The regex pattern to be used - The actual string - The message to display in case of failure - - - - Asserts that a string does not match an expected regular expression pattern. - - The regex pattern to be used - The actual string - - - - The TestCaseData class represents a set of arguments - and other parameter info to be used for a parameterized - test case. It provides a number of instance modifiers - for use in initializing the test case. - - Note: Instance modifiers are getters that return - the same instance after modifying it's state. - - - - - The argument list to be provided to the test - - - - - The expected result to be returned - - - - - Set to true if this has an expected result - - - - - The expected exception Type - - - - - The FullName of the expected exception - - - - - The name to be used for the test - - - - - The description of the test - - - - - A dictionary of properties, used to add information - to tests without requiring the class to change. - - - - - If true, indicates that the test case is to be ignored - - - - - If true, indicates that the test case is marked explicit - - - - - The reason for ignoring a test case - - - - - Initializes a new instance of the class. - - The arguments. - - - - Initializes a new instance of the class. - - The argument. - - - - Initializes a new instance of the class. - - The first argument. - The second argument. - - - - Initializes a new instance of the class. - - The first argument. - The second argument. - The third argument. - - - - Sets the expected result for the test - - The expected result - A modified TestCaseData - - - - Sets the expected exception type for the test - - Type of the expected exception. - The modified TestCaseData instance - - - - Sets the expected exception type for the test - - FullName of the expected exception. - The modified TestCaseData instance - - - - Sets the name of the test case - - The modified TestCaseData instance - - - - Sets the description for the test case - being constructed. - - The description. - The modified TestCaseData instance. - - - - Applies a category to the test - - - - - - - Applies a named property to the test - - - - - - - - Applies a named property to the test - - - - - - - - Applies a named property to the test - - - - - - - - Ignores this TestCase. - - - - - - Ignores this TestCase, specifying the reason. - - The reason. - - - - - Marks this TestCase as Explicit - - - - - - Marks this TestCase as Explicit, specifying the reason. - - The reason. - - - - - Gets the argument list to be provided to the test - - - - - Gets the expected result - - - - - Returns true if the result has been set - - - - - Gets the expected exception Type - - - - - Gets the FullName of the expected exception - - - - - Gets the name to be used for the test - - - - - Gets the description of the test - - - - - Gets a value indicating whether this is ignored. - - true if ignored; otherwise, false. - - - - Gets a value indicating whether this is explicit. - - true if explicit; otherwise, false. - - - - Gets the ignore reason. - - The ignore reason. - - - - Gets a list of categories associated with this test. - - - - - Gets the property dictionary for this test - - - - - Provide the context information of the current test - - - - - Constructs a TestContext using the provided context dictionary - - A context dictionary - - - - Get the current test context. This is created - as needed. The user may save the context for - use within a test, but it should not be used - outside the test for which it is created. - - - - - Gets a TestAdapter representing the currently executing test in this context. - - - - - Gets a ResultAdapter representing the current result for the test - executing in this context. - - - - - Gets the directory containing the current test assembly. - - - - - Gets the directory to be used for outputing files created - by this test run. - - - - - TestAdapter adapts a Test for consumption by - the user test code. - - - - - Constructs a TestAdapter for this context - - The context dictionary - - - - The name of the test. - - - - - The FullName of the test - - - - - The properties of the test. - - - - - ResultAdapter adapts a TestResult for consumption by - the user test code. - - - - - Construct a ResultAdapter for a context - - The context holding the result - - - - The TestState of current test. This maps to the ResultState - used in nunit.core and is subject to change in the future. - - - - - The TestStatus of current test. This enum will be used - in future versions of NUnit and so is to be preferred - to the TestState value. - - - - - Provides details about a test - - - - - Creates an instance of TestDetails - - The fixture that the test is a member of, if available. - The method that implements the test, if available. - The full name of the test. - A string representing the type of test, e.g. "Test Case". - Indicates if the test represents a suite of tests. - - - - The fixture that the test is a member of, if available. - - - - - The method that implements the test, if available. - - - - - The full name of the test. - - - - - A string representing the type of test, e.g. "Test Case". - - - - - Indicates if the test represents a suite of tests. - - - - - The ResultState enum indicates the result of running a test - - - - - The result is inconclusive - - - - - The test was not runnable. - - - - - The test has been skipped. - - - - - The test has been ignored. - - - - - The test succeeded - - - - - The test failed - - - - - The test encountered an unexpected exception - - - - - The test was cancelled by the user - - - - - The TestStatus enum indicates the result of running a test - - - - - The test was inconclusive - - - - - The test has skipped - - - - - The test succeeded - - - - - The test failed - - - - - Helper class with static methods used to supply constraints - that operate on strings. - - - - - Returns a constraint that succeeds if the actual - value contains the substring supplied as an argument. - - - - - Returns a constraint that fails if the actual - value contains the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value starts with the substring supplied as an argument. - - - - - Returns a constraint that fails if the actual - value starts with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value ends with the substring supplied as an argument. - - - - - Returns a constraint that fails if the actual - value ends with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value matches the Regex pattern supplied as an argument. - - - - - Returns a constraint that fails if the actual - value matches the pattern supplied as an argument. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if all of them succeed. - - - - - TextMessageWriter writes constraint descriptions and messages - in displayable form as a text stream. It tailors the display - of individual message components to form the standard message - format of NUnit assertion failure messages. - - - - - MessageWriter is the abstract base for classes that write - constraint descriptions and messages in some form. The - class has separate methods for writing various components - of a message, allowing implementations to tailor the - presentation as needed. - - - - - Construct a MessageWriter given a culture - - - - - Method to write single line message with optional args, usually - written to precede the general failure message. - - The message to be written - Any arguments used in formatting the message - - - - Method to write single line message with optional args, usually - written to precede the general failure message, at a givel - indentation level. - - The indentation level of the message - The message to be written - Any arguments used in formatting the message - - - - Display Expected and Actual lines for a constraint. This - is called by MessageWriter's default implementation of - WriteMessageTo and provides the generic two-line display. - - The constraint that failed - - - - Display Expected and Actual lines for given values. This - method may be called by constraints that need more control over - the display of actual and expected values than is provided - by the default implementation. - - The expected value - The actual value causing the failure - - - - Display Expected and Actual lines for given values, including - a tolerance value on the Expected line. - - The expected value - The actual value causing the failure - The tolerance within which the test was made - - - - Display the expected and actual string values on separate lines. - If the mismatch parameter is >=0, an additional line is displayed - line containing a caret that points to the mismatch point. - - The expected string value - The actual string value - The point at which the strings don't match or -1 - If true, case is ignored in locating the point where the strings differ - If true, the strings should be clipped to fit the line - - - - Writes the text for a connector. - - The connector. - - - - Writes the text for a predicate. - - The predicate. - - - - Writes the text for an expected value. - - The expected value. - - - - Writes the text for a modifier - - The modifier. - - - - Writes the text for an actual value. - - The actual value. - - - - Writes the text for a generalized value. - - The value. - - - - Writes the text for a collection value, - starting at a particular point, to a max length - - The collection containing elements to write. - The starting point of the elements to write - The maximum number of elements to write - - - - Abstract method to get the max line length - - - - - Prefix used for the expected value line of a message - - - - - Prefix used for the actual value line of a message - - - - - Length of a message prefix - - - - - Construct a TextMessageWriter - - - - - Construct a TextMessageWriter, specifying a user message - and optional formatting arguments. - - - - - - - Method to write single line message with optional args, usually - written to precede the general failure message, at a givel - indentation level. - - The indentation level of the message - The message to be written - Any arguments used in formatting the message - - - - Display Expected and Actual lines for a constraint. This - is called by MessageWriter's default implementation of - WriteMessageTo and provides the generic two-line display. - - The constraint that failed - - - - Display Expected and Actual lines for given values. This - method may be called by constraints that need more control over - the display of actual and expected values than is provided - by the default implementation. - - The expected value - The actual value causing the failure - - - - Display Expected and Actual lines for given values, including - a tolerance value on the expected line. - - The expected value - The actual value causing the failure - The tolerance within which the test was made - - - - Display the expected and actual string values on separate lines. - If the mismatch parameter is >=0, an additional line is displayed - line containing a caret that points to the mismatch point. - - The expected string value - The actual string value - The point at which the strings don't match or -1 - If true, case is ignored in string comparisons - If true, clip the strings to fit the max line length - - - - Writes the text for a connector. - - The connector. - - - - Writes the text for a predicate. - - The predicate. - - - - Write the text for a modifier. - - The modifier. - - - - Writes the text for an expected value. - - The expected value. - - - - Writes the text for an actual value. - - The actual value. - - - - Writes the text for a generalized value. - - The value. - - - - Writes the text for a collection value, - starting at a particular point, to a max length - - The collection containing elements to write. - The starting point of the elements to write - The maximum number of elements to write - - - - Write the generic 'Expected' line for a constraint - - The constraint that failed - - - - Write the generic 'Expected' line for a given value - - The expected value - - - - Write the generic 'Expected' line for a given value - and tolerance. - - The expected value - The tolerance within which the test was made - - - - Write the generic 'Actual' line for a constraint - - The constraint for which the actual value is to be written - - - - Write the generic 'Actual' line for a given value - - The actual value causing a failure - - - - Gets or sets the maximum line length for this writer - - - - - Helper class with properties and methods that supply - constraints that operate on exceptions. - - - - - Creates a constraint specifying the exact type of exception expected - - - - - Creates a constraint specifying the exact type of exception expected - - - - - Creates a constraint specifying the type of exception expected - - - - - Creates a constraint specifying the type of exception expected - - - - - Creates a constraint specifying an expected exception - - - - - Creates a constraint specifying an exception with a given InnerException - - - - - Creates a constraint specifying an expected TargetInvocationException - - - - - Creates a constraint specifying an expected TargetInvocationException - - - - - Creates a constraint specifying an expected TargetInvocationException - - - - - Creates a constraint specifying that no exception is thrown - - - - - Attribute used to apply a category to a test - - - - - The name of the category - - - - - Construct attribute for a given category based on - a name. The name may not contain the characters ',', - '+', '-' or '!'. However, this is not checked in the - constructor since it would cause an error to arise at - as the test was loaded without giving a clear indication - of where the problem is located. The error is handled - in NUnitFramework.cs by marking the test as not - runnable. - - The name of the category - - - - Protected constructor uses the Type name as the name - of the category. - - - - - The name of the category - - - - - Used to mark a field for use as a datapoint when executing a theory - within the same fixture that requires an argument of the field's Type. - - - - - Used to mark an array as containing a set of datapoints to be used - executing a theory within the same fixture that requires an argument - of the Type of the array elements. - - - - - Attribute used to provide descriptive text about a - test case or fixture. - - - - - Construct the attribute - - Text describing the test - - - - Gets the test description - - - - - Enumeration indicating how the expected message parameter is to be used - - - - Expect an exact match - - - Expect a message containing the parameter string - - - Match the regular expression provided as a parameter - - - Expect a message that starts with the parameter string - - - - ExpectedExceptionAttribute - - - - - - Constructor for a non-specific exception - - - - - Constructor for a given type of exception - - The type of the expected exception - - - - Constructor for a given exception name - - The full name of the expected exception - - - - Gets or sets the expected exception type - - - - - Gets or sets the full Type name of the expected exception - - - - - Gets or sets the expected message text - - - - - Gets or sets the user message displayed in case of failure - - - - - Gets or sets the type of match to be performed on the expected message - - - - - Gets the name of a method to be used as an exception handler - - - - - ExplicitAttribute marks a test or test fixture so that it will - only be run if explicitly executed from the gui or command line - or if it is included by use of a filter. The test will not be - run simply because an enclosing suite is run. - - - - - Default constructor - - - - - Constructor with a reason - - The reason test is marked explicit - - - - The reason test is marked explicit - - - - - Attribute used to mark a test that is to be ignored. - Ignored tests result in a warning message when the - tests are run. - - - - - Constructs the attribute without giving a reason - for ignoring the test. - - - - - Constructs the attribute giving a reason for ignoring the test - - The reason for ignoring the test - - - - The reason for ignoring a test - - - - - Abstract base for Attributes that are used to include tests - in the test run based on environmental settings. - - - - - Constructor with no included items specified, for use - with named property syntax. - - - - - Constructor taking one or more included items - - Comma-delimited list of included items - - - - Name of the item that is needed in order for - a test to run. Multiple itemss may be given, - separated by a comma. - - - - - Name of the item to be excluded. Multiple items - may be given, separated by a comma. - - - - - The reason for including or excluding the test - - - - - PlatformAttribute is used to mark a test fixture or an - individual method as applying to a particular platform only. - - - - - Constructor with no platforms specified, for use - with named property syntax. - - - - - Constructor taking one or more platforms - - Comma-deliminted list of platforms - - - - CultureAttribute is used to mark a test fixture or an - individual method as applying to a particular Culture only. - - - - - Constructor with no cultures specified, for use - with named property syntax. - - - - - Constructor taking one or more cultures - - Comma-deliminted list of cultures - - - - Marks a test to use a combinatorial join of any argument data - provided. NUnit will create a test case for every combination of - the arguments provided. This can result in a large number of test - cases and so should be used judiciously. This is the default join - type, so the attribute need not be used except as documentation. - - - - - PropertyAttribute is used to attach information to a test as a name/value pair.. - - - - - Construct a PropertyAttribute with a name and string value - - The name of the property - The property value - - - - Construct a PropertyAttribute with a name and int value - - The name of the property - The property value - - - - Construct a PropertyAttribute with a name and double value - - The name of the property - The property value - - - - Constructor for derived classes that set the - property dictionary directly. - - - - - Constructor for use by derived classes that use the - name of the type as the property name. Derived classes - must ensure that the Type of the property value is - a standard type supported by the BCL. Any custom - types will cause a serialization Exception when - in the client. - - - - - Gets the property dictionary for this attribute - - - - - Default constructor - - - - - Marks a test to use pairwise join of any argument data provided. - NUnit will attempt too excercise every pair of argument values at - least once, using as small a number of test cases as it can. With - only two arguments, this is the same as a combinatorial join. - - - - - Default constructor - - - - - Marks a test to use a sequential join of any argument data - provided. NUnit will use arguements for each parameter in - sequence, generating test cases up to the largest number - of argument values provided and using null for any arguments - for which it runs out of values. Normally, this should be - used with the same number of arguments for each parameter. - - - - - Default constructor - - - - - Summary description for MaxTimeAttribute. - - - - - Construct a MaxTimeAttribute, given a time in milliseconds. - - The maximum elapsed time in milliseconds - - - - RandomAttribute is used to supply a set of random values - to a single parameter of a parameterized test. - - - - - ValuesAttribute is used to provide literal arguments for - an individual parameter of a test. - - - - - Abstract base class for attributes that apply to parameters - and supply data for the parameter. - - - - - Gets the data to be provided to the specified parameter - - - - - The collection of data to be returned. Must - be set by any derived attribute classes. - We use an object[] so that the individual - elements may have their type changed in GetData - if necessary. - - - - - Construct with one argument - - - - - - Construct with two arguments - - - - - - - Construct with three arguments - - - - - - - - Construct with an array of arguments - - - - - - Get the collection of values to be used as arguments - - - - - Construct a set of doubles from 0.0 to 1.0, - specifying only the count. - - - - - - Construct a set of doubles from min to max - - - - - - - - Construct a set of ints from min to max - - - - - - - - Get the collection of values to be used as arguments - - - - - RangeAttribute is used to supply a range of values to an - individual parameter of a parameterized test. - - - - - Construct a range of ints using default step of 1 - - - - - - - Construct a range of ints specifying the step size - - - - - - - - Construct a range of longs - - - - - - - - Construct a range of doubles - - - - - - - - Construct a range of floats - - - - - - - - RepeatAttribute may be applied to test case in order - to run it multiple times. - - - - - Construct a RepeatAttribute - - The number of times to run the test - - - - RequiredAddinAttribute may be used to indicate the names of any addins - that must be present in order to run some or all of the tests in an - assembly. If the addin is not loaded, the entire assembly is marked - as NotRunnable. - - - - - Initializes a new instance of the class. - - The required addin. - - - - Gets the name of required addin. - - The required addin name. - - - - Summary description for SetCultureAttribute. - - - - - Construct given the name of a culture - - - - - - Summary description for SetUICultureAttribute. - - - - - Construct given the name of a culture - - - - - - SetUpAttribute is used in a TestFixture to identify a method - that is called immediately before each test is run. It is - also used in a SetUpFixture to identify the method that is - called once, before any of the subordinate tests are run. - - - - - Attribute used to mark a class that contains one-time SetUp - and/or TearDown methods that apply to all the tests in a - namespace or an assembly. - - - - - Attribute used to mark a static (shared in VB) property - that returns a list of tests. - - - - - Attribute used in a TestFixture to identify a method that is - called immediately after each test is run. It is also used - in a SetUpFixture to identify the method that is called once, - after all subordinate tests have run. In either case, the method - is guaranteed to be called, even if an exception is thrown. - - - - - Provide actions to execute before and after tests. - - - - - When implemented by an attribute, this interface implemented to provide actions to execute before and after tests. - - - - - Executed before each test is run - - Provides details about the test that is going to be run. - - - - Executed after each test is run - - Provides details about the test that has just been run. - - - - Provides the target for the action attribute - - The target for the action attribute - - - - Method called before each test - - Info about the test to be run - - - - Method called after each test - - Info about the test that was just run - - - - Gets or sets the ActionTargets for this attribute - - - - - Adding this attribute to a method within a - class makes the method callable from the NUnit test runner. There is a property - called Description which is optional which you can provide a more detailed test - description. This class cannot be inherited. - - - - [TestFixture] - public class Fixture - { - [Test] - public void MethodToTest() - {} - - [Test(Description = "more detailed description")] - publc void TestDescriptionMethod() - {} - } - - - - - - Descriptive text for this test - - - - - TestCaseAttribute is used to mark parameterized test cases - and provide them with their arguments. - - - - - Construct a TestCaseAttribute with a list of arguments. - This constructor is not CLS-Compliant - - - - - - Construct a TestCaseAttribute with a single argument - - - - - - Construct a TestCaseAttribute with a two arguments - - - - - - - Construct a TestCaseAttribute with a three arguments - - - - - - - - Gets the list of arguments to a test case - - - - - Gets or sets the expected result. Use - ExpectedResult by preference. - - The result. - - - - Gets or sets the expected result. - - The result. - - - - Gets a flag indicating whether an expected - result has been set. - - - - - Gets a list of categories associated with this test; - - - - - Gets or sets the category associated with this test. - May be a single category or a comma-separated list. - - - - - Gets or sets the expected exception. - - The expected exception. - - - - Gets or sets the name the expected exception. - - The expected name of the exception. - - - - Gets or sets the expected message of the expected exception - - The expected message of the exception. - - - - Gets or sets the type of match to be performed on the expected message - - - - - Gets or sets the description. - - The description. - - - - Gets or sets the name of the test. - - The name of the test. - - - - Gets or sets the ignored status of the test - - - - - Gets or sets the ignored status of the test - - - - - Gets or sets the explicit status of the test - - - - - Gets or sets the reason for not running the test - - - - - Gets or sets the reason for not running the test. - Set has the side effect of marking the test as ignored. - - The ignore reason. - - - - FactoryAttribute indicates the source to be used to - provide test cases for a test method. - - - - - Construct with the name of the data source, which must - be a property, field or method of the test class itself. - - An array of the names of the factories that will provide data - - - - Construct with a Type, which must implement IEnumerable - - The Type that will provide data - - - - Construct with a Type and name. - that don't support params arrays. - - The Type that will provide data - The name of the method, property or field that will provide data - - - - The name of a the method, property or fiend to be used as a source - - - - - A Type to be used as a source - - - - - Gets or sets the category associated with this test. - May be a single category or a comma-separated list. - - - - - [TestFixture] - public class ExampleClass - {} - - - - - Default constructor - - - - - Construct with a object[] representing a set of arguments. - In .NET 2.0, the arguments may later be separated into - type arguments and constructor arguments. - - - - - - Descriptive text for this fixture - - - - - Gets and sets the category for this fixture. - May be a comma-separated list of categories. - - - - - Gets a list of categories for this fixture - - - - - The arguments originally provided to the attribute - - - - - Gets or sets a value indicating whether this should be ignored. - - true if ignore; otherwise, false. - - - - Gets or sets the ignore reason. May set Ignored as a side effect. - - The ignore reason. - - - - Get or set the type arguments. If not set - explicitly, any leading arguments that are - Types are taken as type arguments. - - - - - Attribute used to identify a method that is - called before any tests in a fixture are run. - - - - - Attribute used to identify a method that is called after - all the tests in a fixture have run. The method is - guaranteed to be called, even if an exception is thrown. - - - - - Adding this attribute to a method within a - class makes the method callable from the NUnit test runner. There is a property - called Description which is optional which you can provide a more detailed test - description. This class cannot be inherited. - - - - [TestFixture] - public class Fixture - { - [Test] - public void MethodToTest() - {} - - [Test(Description = "more detailed description")] - publc void TestDescriptionMethod() - {} - } - - - - - - Used on a method, marks the test with a timeout value in milliseconds. - The test will be run in a separate thread and is cancelled if the timeout - is exceeded. Used on a method or assembly, sets the default timeout - for all contained test methods. - - - - - Construct a TimeoutAttribute given a time in milliseconds - - The timeout value in milliseconds - - - - Marks a test that must run in the STA, causing it - to run in a separate thread if necessary. - - On methods, you may also use STAThreadAttribute - to serve the same purpose. - - - - - Construct a RequiresSTAAttribute - - - - - Marks a test that must run in the MTA, causing it - to run in a separate thread if necessary. - - On methods, you may also use MTAThreadAttribute - to serve the same purpose. - - - - - Construct a RequiresMTAAttribute - - - - - Marks a test that must run on a separate thread. - - - - - Construct a RequiresThreadAttribute - - - - - Construct a RequiresThreadAttribute, specifying the apartment - - - - - ValueSourceAttribute indicates the source to be used to - provide data for one parameter of a test method. - - - - - Construct with the name of the factory - for use with languages - that don't support params arrays. - - The name of the data source to be used - - - - Construct with a Type and name - for use with languages - that don't support params arrays. - - The Type that will provide data - The name of the method, property or field that will provide data - - - - The name of a the method, property or fiend to be used as a source - - - - - A Type to be used as a source - - - - - AllItemsConstraint applies another constraint to each - item in a collection, succeeding if they all succeed. - - - - - Abstract base class used for prefixes - - - - - The Constraint class is the base of all built-in constraints - within NUnit. It provides the operator overloads used to combine - constraints. - - - - - The IConstraintExpression interface is implemented by all - complete and resolvable constraints and expressions. - - - - - Return the top-level constraint for this expression - - - - - - Static UnsetObject used to detect derived constraints - failing to set the actual value. - - - - - The actual value being tested against a constraint - - - - - The display name of this Constraint for use by ToString() - - - - - Argument fields used by ToString(); - - - - - The builder holding this constraint - - - - - Construct a constraint with no arguments - - - - - Construct a constraint with one argument - - - - - Construct a constraint with two arguments - - - - - Sets the ConstraintBuilder holding this constraint - - - - - Write the failure message to the MessageWriter provided - as an argument. The default implementation simply passes - the constraint and the actual value to the writer, which - then displays the constraint description and the value. - - Constraints that need to provide additional details, - such as where the error occured can override this. - - The MessageWriter on which to display the message - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Test whether the constraint is satisfied by an - ActualValueDelegate that returns the value to be tested. - The default implementation simply evaluates the delegate - but derived classes may override it to provide for delayed - processing. - - An - True for success, false for failure - - - - Test whether the constraint is satisfied by a given reference. - The default implementation simply dereferences the value but - derived classes may override it to provide for delayed processing. - - A reference to the value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a - MessageWriter. The default implementation simply writes - the raw value of actual, leaving it to the writer to - perform any formatting. - - The writer on which the actual value is displayed - - - - Default override of ToString returns the constraint DisplayName - followed by any arguments within angle brackets. - - - - - - Returns the string representation of this constraint - - - - - This operator creates a constraint that is satisfied only if both - argument constraints are satisfied. - - - - - This operator creates a constraint that is satisfied if either - of the argument constraints is satisfied. - - - - - This operator creates a constraint that is satisfied if the - argument constraint is not satisfied. - - - - - Returns a DelayedConstraint with the specified delay time. - - The delay in milliseconds. - - - - - Returns a DelayedConstraint with the specified delay time - and polling interval. - - The delay in milliseconds. - The interval at which to test the constraint. - - - - - The display name of this Constraint for use by ToString(). - The default value is the name of the constraint with - trailing "Constraint" removed. Derived classes may set - this to another name in their constructors. - - - - - Returns a ConstraintExpression by appending And - to the current constraint. - - - - - Returns a ConstraintExpression by appending And - to the current constraint. - - - - - Returns a ConstraintExpression by appending Or - to the current constraint. - - - - - Class used to detect any derived constraints - that fail to set the actual value in their - Matches override. - - - - - The base constraint - - - - - Construct given a base constraint - - - - - - Construct an AllItemsConstraint on top of an existing constraint - - - - - - Apply the item constraint to each item in the collection, - failing if any item fails. - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - AndConstraint succeeds only if both members succeed. - - - - - BinaryConstraint is the abstract base of all constraints - that combine two other constraints in some fashion. - - - - - The first constraint being combined - - - - - The second constraint being combined - - - - - Construct a BinaryConstraint from two other constraints - - The first constraint - The second constraint - - - - Create an AndConstraint from two other constraints - - The first constraint - The second constraint - - - - Apply both member constraints to an actual value, succeeding - succeeding only if both of them succeed. - - The actual value - True if the constraints both succeeded - - - - Write a description for this contraint to a MessageWriter - - The MessageWriter to receive the description - - - - Write the actual value for a failing constraint test to a - MessageWriter. The default implementation simply writes - the raw value of actual, leaving it to the writer to - perform any formatting. - - The writer on which the actual value is displayed - - - - AssignableFromConstraint is used to test that an object - can be assigned from a given Type. - - - - - TypeConstraint is the abstract base for constraints - that take a Type as their expected value. - - - - - The expected Type used by the constraint - - - - - Construct a TypeConstraint for a given Type - - - - - - Write the actual value for a failing constraint test to a - MessageWriter. TypeConstraints override this method to write - the name of the type. - - The writer on which the actual value is displayed - - - - Construct an AssignableFromConstraint for the type provided - - - - - - Test whether an object can be assigned from the specified type - - The object to be tested - True if the object can be assigned a value of the expected Type, otherwise false. - - - - Write a description of this constraint to a MessageWriter - - The MessageWriter to use - - - - AssignableToConstraint is used to test that an object - can be assigned to a given Type. - - - - - Construct an AssignableToConstraint for the type provided - - - - - - Test whether an object can be assigned to the specified type - - The object to be tested - True if the object can be assigned a value of the expected Type, otherwise false. - - - - Write a description of this constraint to a MessageWriter - - The MessageWriter to use - - - - AttributeConstraint tests that a specified attribute is present - on a Type or other provider and that the value of the attribute - satisfies some other constraint. - - - - - Constructs an AttributeConstraint for a specified attriute - Type and base constraint. - - - - - - - Determines whether the Type or other provider has the - expected attribute and if its value matches the - additional constraint specified. - - - - - Writes a description of the attribute to the specified writer. - - - - - Writes the actual value supplied to the specified writer. - - - - - Returns a string representation of the constraint. - - - - - AttributeExistsConstraint tests for the presence of a - specified attribute on a Type. - - - - - Constructs an AttributeExistsConstraint for a specific attribute Type - - - - - - Tests whether the object provides the expected attribute. - - A Type, MethodInfo, or other ICustomAttributeProvider - True if the expected attribute is present, otherwise false - - - - Writes the description of the constraint to the specified writer - - - - - BasicConstraint is the abstract base for constraints that - perform a simple comparison to a constant value. - - - - - Initializes a new instance of the class. - - The expected. - The description. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - BinarySerializableConstraint tests whether - an object is serializable in binary format. - - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a - MessageWriter. The default implementation simply writes - the raw value of actual, leaving it to the writer to - perform any formatting. - - The writer on which the actual value is displayed - - - - Returns the string representation - - - - - CollectionConstraint is the abstract base class for - constraints that operate on collections. - - - - - Construct an empty CollectionConstraint - - - - - Construct a CollectionConstraint - - - - - - Determines whether the specified enumerable is empty. - - The enumerable. - - true if the specified enumerable is empty; otherwise, false. - - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Protected method to be implemented by derived classes - - - - - - - CollectionContainsConstraint is used to test whether a collection - contains an expected object as a member. - - - - - CollectionItemsEqualConstraint is the abstract base class for all - collection constraints that apply some notion of item equality - as a part of their operation. - - - - - Construct an empty CollectionConstraint - - - - - Construct a CollectionConstraint - - - - - - Flag the constraint to use the supplied EqualityAdapter. - NOTE: For internal use only. - - The EqualityAdapter to use. - Self. - - - - Flag the constraint to use the supplied IComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied Comparison object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IEqualityComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IEqualityComparer object. - - The IComparer object to use. - Self. - - - - Compares two collection members for equality - - - - - Return a new CollectionTally for use in making tests - - The collection to be included in the tally - - - - Flag the constraint to ignore case and return self. - - - - - Construct a CollectionContainsConstraint - - - - - - Test whether the expected item is contained in the collection - - - - - - - Write a descripton of the constraint to a MessageWriter - - - - - - CollectionEquivalentCOnstraint is used to determine whether two - collections are equivalent. - - - - - Construct a CollectionEquivalentConstraint - - - - - - Test whether two collections are equivalent - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - CollectionOrderedConstraint is used to test whether a collection is ordered. - - - - - Construct a CollectionOrderedConstraint - - - - - Modifies the constraint to use an IComparer and returns self. - - - - - Modifies the constraint to use an IComparer<T> and returns self. - - - - - Modifies the constraint to use a Comparison<T> and returns self. - - - - - Modifies the constraint to test ordering by the value of - a specified property and returns self. - - - - - Test whether the collection is ordered - - - - - - - Write a description of the constraint to a MessageWriter - - - - - - Returns the string representation of the constraint. - - - - - - If used performs a reverse comparison - - - - - CollectionSubsetConstraint is used to determine whether - one collection is a subset of another - - - - - Construct a CollectionSubsetConstraint - - The collection that the actual value is expected to be a subset of - - - - Test whether the actual collection is a subset of - the expected collection provided. - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - CollectionTally counts (tallies) the number of - occurences of each object in one or more enumerations. - - - - - Construct a CollectionTally object from a comparer and a collection - - - - - Try to remove an object from the tally - - The object to remove - True if successful, false if the object was not found - - - - Try to remove a set of objects from the tally - - The objects to remove - True if successful, false if any object was not found - - - - The number of objects remaining in the tally - - - - - ComparisonAdapter class centralizes all comparisons of - values in NUnit, adapting to the use of any provided - IComparer, IComparer<T> or Comparison<T> - - - - - Returns a ComparisonAdapter that wraps an IComparer - - - - - Returns a ComparisonAdapter that wraps an IComparer<T> - - - - - Returns a ComparisonAdapter that wraps a Comparison<T> - - - - - Compares two objects - - - - - Gets the default ComparisonAdapter, which wraps an - NUnitComparer object. - - - - - Construct a ComparisonAdapter for an IComparer - - - - - Compares two objects - - - - - - - - Construct a default ComparisonAdapter - - - - - ComparisonAdapter<T> extends ComparisonAdapter and - allows use of an IComparer<T> or Comparison<T> - to actually perform the comparison. - - - - - Construct a ComparisonAdapter for an IComparer<T> - - - - - Compare a Type T to an object - - - - - Construct a ComparisonAdapter for a Comparison<T> - - - - - Compare a Type T to an object - - - - - Abstract base class for constraints that compare values to - determine if one is greater than, equal to or less than - the other. This class supplies the Using modifiers. - - - - - ComparisonAdapter to be used in making the comparison - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - - - - Modifies the constraint to use an IComparer and returns self - - - - - Modifies the constraint to use an IComparer<T> and returns self - - - - - Modifies the constraint to use a Comparison<T> and returns self - - - - - Delegate used to delay evaluation of the actual value - to be used in evaluating a constraint - - - - - ConstraintBuilder maintains the stacks that are used in - processing a ConstraintExpression. An OperatorStack - is used to hold operators that are waiting for their - operands to be reognized. a ConstraintStack holds - input constraints as well as the results of each - operator applied. - - - - - Initializes a new instance of the class. - - - - - Appends the specified operator to the expression by first - reducing the operator stack and then pushing the new - operator on the stack. - - The operator to push. - - - - Appends the specified constraint to the expresson by pushing - it on the constraint stack. - - The constraint to push. - - - - Sets the top operator right context. - - The right context. - - - - Reduces the operator stack until the topmost item - precedence is greater than or equal to the target precedence. - - The target precedence. - - - - Resolves this instance, returning a Constraint. If the builder - is not currently in a resolvable state, an exception is thrown. - - The resolved constraint - - - - Gets a value indicating whether this instance is resolvable. - - - true if this instance is resolvable; otherwise, false. - - - - - OperatorStack is a type-safe stack for holding ConstraintOperators - - - - - Initializes a new instance of the class. - - The builder. - - - - Pushes the specified operator onto the stack. - - The op. - - - - Pops the topmost operator from the stack. - - - - - - Gets a value indicating whether this is empty. - - true if empty; otherwise, false. - - - - Gets the topmost operator without modifying the stack. - - The top. - - - - ConstraintStack is a type-safe stack for holding Constraints - - - - - Initializes a new instance of the class. - - The builder. - - - - Pushes the specified constraint. As a side effect, - the constraint's builder field is set to the - ConstraintBuilder owning this stack. - - The constraint. - - - - Pops this topmost constrait from the stack. - As a side effect, the constraint's builder - field is set to null. - - - - - - Gets a value indicating whether this is empty. - - true if empty; otherwise, false. - - - - Gets the topmost constraint without modifying the stack. - - The topmost constraint - - - - ConstraintExpression represents a compound constraint in the - process of being constructed from a series of syntactic elements. - - Individual elements are appended to the expression as they are - reognized. Once an actual Constraint is appended, the expression - returns a resolvable Constraint. - - - - - ConstraintExpressionBase is the abstract base class for the - ConstraintExpression class, which represents a - compound constraint in the process of being constructed - from a series of syntactic elements. - - NOTE: ConstraintExpressionBase is separate because the - ConstraintExpression class was generated in earlier - versions of NUnit. The two classes may be combined - in a future version. - - - - - The ConstraintBuilder holding the elements recognized so far - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the - class passing in a ConstraintBuilder, which may be pre-populated. - - The builder. - - - - Returns a string representation of the expression as it - currently stands. This should only be used for testing, - since it has the side-effect of resolving the expression. - - - - - - Appends an operator to the expression and returns the - resulting expression itself. - - - - - Appends a self-resolving operator to the expression and - returns a new ResolvableConstraintExpression. - - - - - Appends a constraint to the expression and returns that - constraint, which is associated with the current state - of the expression being built. - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the - class passing in a ConstraintBuilder, which may be pre-populated. - - The builder. - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding only if a specified number of them succeed. - - - - - Returns a new PropertyConstraintExpression, which will either - test for the existence of the named property on the object - being tested or apply any following constraint to that property. - - - - - Returns a new AttributeConstraint checking for the - presence of a particular attribute on an object. - - - - - Returns a new AttributeConstraint checking for the - presence of a particular attribute on an object. - - - - - Returns the constraint provided as an argument - used to allow custom - custom constraints to easily participate in the syntax. - - - - - Returns the constraint provided as an argument - used to allow custom - custom constraints to easily participate in the syntax. - - - - - Returns a constraint that tests two items for equality - - - - - Returns a constraint that tests that two references are the same object - - - - - Returns a constraint that tests whether the - actual value is greater than the suppled argument - - - - - Returns a constraint that tests whether the - actual value is greater than or equal to the suppled argument - - - - - Returns a constraint that tests whether the - actual value is greater than or equal to the suppled argument - - - - - Returns a constraint that tests whether the - actual value is less than the suppled argument - - - - - Returns a constraint that tests whether the - actual value is less than or equal to the suppled argument - - - - - Returns a constraint that tests whether the - actual value is less than or equal to the suppled argument - - - - - Returns a constraint that tests whether the actual - value is of the exact type supplied as an argument. - - - - - Returns a constraint that tests whether the actual - value is of the exact type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is of the type supplied as an argument or a derived type. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is assignable from the type supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is a collection containing the same elements as the - collection supplied as an argument. - - - - - Returns a constraint that tests whether the actual value - is a subset of the collection supplied as an argument. - - - - - Returns a new CollectionContainsConstraint checking for the - presence of a particular object in the collection. - - - - - Returns a new CollectionContainsConstraint checking for the - presence of a particular object in the collection. - - - - - Returns a new ContainsConstraint. This constraint - will, in turn, make use of the appropriate second-level - constraint, depending on the type of the actual argument. - This overload is only used if the item sought is a string, - since any other type implies that we are looking for a - collection member. - - - - - Returns a constraint that succeeds if the actual - value contains the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value contains the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value starts with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value starts with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value ends with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value ends with the substring supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value matches the regular expression supplied as an argument. - - - - - Returns a constraint that succeeds if the actual - value matches the regular expression supplied as an argument. - - - - - Returns a constraint that tests whether the path provided - is the same as an expected path after canonicalization. - - - - - Returns a constraint that tests whether the path provided - is the same path or under an expected path after canonicalization. - - - - - Returns a constraint that tests whether the path provided - is the same path or under an expected path after canonicalization. - - - - - Returns a constraint that tests whether the actual value falls - within a specified range. - - - - - Returns a ConstraintExpression that negates any - following constraint. - - - - - Returns a ConstraintExpression that negates any - following constraint. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if all of them succeed. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if at least one of them succeeds. - - - - - Returns a ConstraintExpression, which will apply - the following constraint to all members of a collection, - succeeding if all of them fail. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the Length property of the object being tested. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the Count property of the object being tested. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the Message property of the object being tested. - - - - - Returns a new ConstraintExpression, which will apply the following - constraint to the InnerException property of the object being tested. - - - - - With is currently a NOP - reserved for future use. - - - - - Returns a constraint that tests for null - - - - - Returns a constraint that tests for True - - - - - Returns a constraint that tests for False - - - - - Returns a constraint that tests for a positive value - - - - - Returns a constraint that tests for a negative value - - - - - Returns a constraint that tests for NaN - - - - - Returns a constraint that tests for empty - - - - - Returns a constraint that tests whether a collection - contains all unique items. - - - - - Returns a constraint that tests whether an object graph is serializable in binary format. - - - - - Returns a constraint that tests whether an object graph is serializable in xml format. - - - - - Returns a constraint that tests whether a collection is ordered - - - - - ContainsConstraint tests a whether a string contains a substring - or a collection contains an object. It postpones the decision of - which test to use until the type of the actual argument is known. - This allows testing whether a string is contained in a collection - or as a substring of another string using the same syntax. - - - - - Initializes a new instance of the class. - - The expected. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Flag the constraint to use the supplied IComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied Comparison object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IEqualityComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IEqualityComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to ignore case and return self. - - - - - Applies a delay to the match so that a match can be evaluated in the future. - - - - - Creates a new DelayedConstraint - - The inner constraint two decorate - The time interval after which the match is performed - If the value of is less than 0 - - - - Creates a new DelayedConstraint - - The inner constraint two decorate - The time interval after which the match is performed - The time interval used for polling - If the value of is less than 0 - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for if the base constraint fails, false if it succeeds - - - - Test whether the constraint is satisfied by a delegate - - The delegate whose value is to be tested - True for if the base constraint fails, false if it succeeds - - - - Test whether the constraint is satisfied by a given reference. - Overridden to wait for the specified delay period before - calling the base constraint with the dereferenced value. - - A reference to the value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a MessageWriter. - - The writer on which the actual value is displayed - - - - Returns the string representation of the constraint. - - - - - EmptyCollectionConstraint tests whether a collection is empty. - - - - - Check that the collection is empty - - - - - - - Write the constraint description to a MessageWriter - - - - - - EmptyConstraint tests a whether a string or collection is empty, - postponing the decision about which test is applied until the - type of the actual argument is known. - - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - EmptyDirectoryConstraint is used to test that a directory is empty - - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a - MessageWriter. The default implementation simply writes - the raw value of actual, leaving it to the writer to - perform any formatting. - - The writer on which the actual value is displayed - - - - EmptyStringConstraint tests whether a string is empty. - - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - EndsWithConstraint can test whether a string ends - with an expected substring. - - - - - StringConstraint is the abstract base for constraints - that operate on strings. It supports the IgnoreCase - modifier for string operations. - - - - - The expected value - - - - - Indicates whether tests should be case-insensitive - - - - - Constructs a StringConstraint given an expected value - - The expected value - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Test whether the constraint is satisfied by a given string - - The string to be tested - True for success, false for failure - - - - Modify the constraint to ignore case in matching. - - - - - Initializes a new instance of the class. - - The expected string - - - - Test whether the constraint is matched by the actual value. - This is a template method, which calls the IsMatch method - of the derived class. - - - - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - EqualConstraint is able to compare an actual value with the - expected value provided in its constructor. Two objects are - considered equal if both are null, or if both have the same - value. NUnit has special semantics for some object types. - - - - - If true, strings in error messages will be clipped - - - - - NUnitEqualityComparer used to test equality. - - - - - Initializes a new instance of the class. - - The expected value. - - - - Flag the constraint to use a tolerance when determining equality. - - Tolerance value to be used - Self. - - - - Flag the constraint to use the supplied IComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied Comparison object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IEqualityComparer object. - - The IComparer object to use. - Self. - - - - Flag the constraint to use the supplied IEqualityComparer object. - - The IComparer object to use. - Self. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write a failure message. Overridden to provide custom - failure messages for EqualConstraint. - - The MessageWriter to write to - - - - Write description of this constraint - - The MessageWriter to write to - - - - Display the failure information for two collections that did not match. - - The MessageWriter on which to display - The expected collection. - The actual collection - The depth of this failure in a set of nested collections - - - - Displays a single line showing the types and sizes of the expected - and actual enumerations, collections or arrays. If both are identical, - the value is only shown once. - - The MessageWriter on which to display - The expected collection or array - The actual collection or array - The indentation level for the message line - - - - Displays a single line showing the point in the expected and actual - arrays at which the comparison failed. If the arrays have different - structures or dimensions, both values are shown. - - The MessageWriter on which to display - The expected array - The actual array - Index of the failure point in the underlying collections - The indentation level for the message line - - - - Display the failure information for two IEnumerables that did not match. - - The MessageWriter on which to display - The expected enumeration. - The actual enumeration - The depth of this failure in a set of nested collections - - - - Flag the constraint to ignore case and return self. - - - - - Flag the constraint to suppress string clipping - and return self. - - - - - Flag the constraint to compare arrays as collections - and return self. - - - - - Switches the .Within() modifier to interpret its tolerance as - a distance in representable values (see remarks). - - Self. - - Ulp stands for "unit in the last place" and describes the minimum - amount a given value can change. For any integers, an ulp is 1 whole - digit. For floating point values, the accuracy of which is better - for smaller numbers and worse for larger numbers, an ulp depends - on the size of the number. Using ulps for comparison of floating - point results instead of fixed tolerances is safer because it will - automatically compensate for the added inaccuracy of larger numbers. - - - - - Switches the .Within() modifier to interpret its tolerance as - a percentage that the actual values is allowed to deviate from - the expected value. - - Self - - - - Causes the tolerance to be interpreted as a TimeSpan in days. - - Self - - - - Causes the tolerance to be interpreted as a TimeSpan in hours. - - Self - - - - Causes the tolerance to be interpreted as a TimeSpan in minutes. - - Self - - - - Causes the tolerance to be interpreted as a TimeSpan in seconds. - - Self - - - - Causes the tolerance to be interpreted as a TimeSpan in milliseconds. - - Self - - - - Causes the tolerance to be interpreted as a TimeSpan in clock ticks. - - Self - - - - EqualityAdapter class handles all equality comparisons - that use an IEqualityComparer, IEqualityComparer<T> - or a ComparisonAdapter. - - - - - Compares two objects, returning true if they are equal - - - - - Returns true if the two objects can be compared by this adapter. - The base adapter cannot handle IEnumerables except for strings. - - - - - Returns an EqualityAdapter that wraps an IComparer. - - - - - Returns an EqualityAdapter that wraps an IEqualityComparer. - - - - - Returns an EqualityAdapter that wraps an IEqualityComparer<T>. - - - - - Returns an EqualityAdapter that wraps an IComparer<T>. - - - - - Returns an EqualityAdapter that wraps a Comparison<T>. - - - - - EqualityAdapter that wraps an IComparer. - - - - - Returns true if the two objects can be compared by this adapter. - Generic adapter requires objects of the specified type. - - - - - EqualityAdapter that wraps an IComparer. - - - - - EqualityAdapterList represents a list of EqualityAdapters - in a common class across platforms. - - - - - ExactCountConstraint applies another constraint to each - item in a collection, succeeding only if a specified - number of items succeed. - - - - - Construct an ExactCountConstraint on top of an existing constraint - - - - - - - Apply the item constraint to each item in the collection, - succeeding only if the expected number of items pass. - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - ExactTypeConstraint is used to test that an object - is of the exact type provided in the constructor - - - - - Construct an ExactTypeConstraint for a given Type - - The expected Type. - - - - Test that an object is of the exact type specified - - The actual value. - True if the tested object is of the exact type provided, otherwise false. - - - - Write the description of this constraint to a MessageWriter - - The MessageWriter to use - - - - ExceptionTypeConstraint is a special version of ExactTypeConstraint - used to provided detailed info about the exception thrown in - an error message. - - - - - Constructs an ExceptionTypeConstraint - - - - - Write the actual value for a failing constraint test to a - MessageWriter. Overriden to write additional information - in the case of an Exception. - - The MessageWriter to use - - - - FailurePoint class represents one point of failure - in an equality test. - - - - - The location of the failure - - - - - The expected value - - - - - The actual value - - - - - Indicates whether the expected value is valid - - - - - Indicates whether the actual value is valid - - - - - FailurePointList represents a set of FailurePoints - in a cross-platform way. - - - - - FalseConstraint tests that the actual value is false - - - - - Initializes a new instance of the class. - - - - Helper routines for working with floating point numbers - - - The floating point comparison code is based on this excellent article: - http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm - - - "ULP" means Unit in the Last Place and in the context of this library refers to - the distance between two adjacent floating point numbers. IEEE floating point - numbers can only represent a finite subset of natural numbers, with greater - accuracy for smaller numbers and lower accuracy for very large numbers. - - - If a comparison is allowed "2 ulps" of deviation, that means the values are - allowed to deviate by up to 2 adjacent floating point values, which might be - as low as 0.0000001 for small numbers or as high as 10.0 for large numbers. - - - - - Compares two floating point values for equality - First floating point value to be compared - Second floating point value t be compared - - Maximum number of representable floating point values that are allowed to - be between the left and the right floating point values - - True if both numbers are equal or close to being equal - - - Floating point values can only represent a finite subset of natural numbers. - For example, the values 2.00000000 and 2.00000024 can be stored in a float, - but nothing inbetween them. - - - This comparison will count how many possible floating point values are between - the left and the right number. If the number of possible values between both - numbers is less than or equal to maxUlps, then the numbers are considered as - being equal. - - - Implementation partially follows the code outlined here: - http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ - - - - - Compares two double precision floating point values for equality - First double precision floating point value to be compared - Second double precision floating point value t be compared - - Maximum number of representable double precision floating point values that are - allowed to be between the left and the right double precision floating point values - - True if both numbers are equal or close to being equal - - - Double precision floating point values can only represent a limited series of - natural numbers. For example, the values 2.0000000000000000 and 2.0000000000000004 - can be stored in a double, but nothing inbetween them. - - - This comparison will count how many possible double precision floating point - values are between the left and the right number. If the number of possible - values between both numbers is less than or equal to maxUlps, then the numbers - are considered as being equal. - - - Implementation partially follows the code outlined here: - http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ - - - - - - Reinterprets the memory contents of a floating point value as an integer value - - - Floating point value whose memory contents to reinterpret - - - The memory contents of the floating point value interpreted as an integer - - - - - Reinterprets the memory contents of a double precision floating point - value as an integer value - - - Double precision floating point value whose memory contents to reinterpret - - - The memory contents of the double precision floating point value - interpreted as an integer - - - - - Reinterprets the memory contents of an integer as a floating point value - - Integer value whose memory contents to reinterpret - - The memory contents of the integer value interpreted as a floating point value - - - - - Reinterprets the memory contents of an integer value as a double precision - floating point value - - Integer whose memory contents to reinterpret - - The memory contents of the integer interpreted as a double precision - floating point value - - - - Union of a floating point variable and an integer - - - The union's value as a floating point variable - - - The union's value as an integer - - - The union's value as an unsigned integer - - - Union of a double precision floating point variable and a long - - - The union's value as a double precision floating point variable - - - The union's value as a long - - - The union's value as an unsigned long - - - - Tests whether a value is greater than the value supplied to its constructor - - - - - The value against which a comparison is to be made - - - - - Initializes a new instance of the class. - - The expected value. - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Tests whether a value is greater than or equal to the value supplied to its constructor - - - - - The value against which a comparison is to be made - - - - - Initializes a new instance of the class. - - The expected value. - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - InstanceOfTypeConstraint is used to test that an object - is of the same type provided or derived from it. - - - - - Construct an InstanceOfTypeConstraint for the type provided - - The expected Type - - - - Test whether an object is of the specified type or a derived type - - The object to be tested - True if the object is of the provided type or derives from it, otherwise false. - - - - Write a description of this constraint to a MessageWriter - - The MessageWriter to use - - - - Tests whether a value is less than the value supplied to its constructor - - - - - The value against which a comparison is to be made - - - - - Initializes a new instance of the class. - - The expected value. - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Tests whether a value is less than or equal to the value supplied to its constructor - - - - - The value against which a comparison is to be made - - - - - Initializes a new instance of the class. - - The expected value. - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Static methods used in creating messages - - - - - Static string used when strings are clipped - - - - - Returns the representation of a type as used in NUnitLite. - This is the same as Type.ToString() except for arrays, - which are displayed with their declared sizes. - - - - - - - Converts any control characters in a string - to their escaped representation. - - The string to be converted - The converted string - - - - Return the a string representation for a set of indices into an array - - Array of indices for which a string is needed - - - - Get an array of indices representing the point in a enumerable, - collection or array corresponding to a single int index into the - collection. - - The collection to which the indices apply - Index in the collection - Array of indices - - - - Clip a string to a given length, starting at a particular offset, returning the clipped - string with ellipses representing the removed parts - - The string to be clipped - The maximum permitted length of the result string - The point at which to start clipping - The clipped string - - - - Clip the expected and actual strings in a coordinated fashion, - so that they may be displayed together. - - - - - - - - - Shows the position two strings start to differ. Comparison - starts at the start index. - - The expected string - The actual string - The index in the strings at which comparison should start - Boolean indicating whether case should be ignored - -1 if no mismatch found, or the index where mismatch found - - - - NaNConstraint tests that the actual value is a double or float NaN - - - - - Test that the actual value is an NaN - - - - - - - Write the constraint description to a specified writer - - - - - - NoItemConstraint applies another constraint to each - item in a collection, failing if any of them succeeds. - - - - - Construct a NoItemConstraint on top of an existing constraint - - - - - - Apply the item constraint to each item in the collection, - failing if any item fails. - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - NotConstraint negates the effect of some other constraint - - - - - Initializes a new instance of the class. - - The base constraint to be negated. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for if the base constraint fails, false if it succeeds - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a MessageWriter. - - The writer on which the actual value is displayed - - - - NullConstraint tests that the actual value is null - - - - - Initializes a new instance of the class. - - - - - NullEmptyStringConstraint tests whether a string is either null or empty. - - - - - Constructs a new NullOrEmptyStringConstraint - - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - The Numerics class contains common operations on numeric values. - - - - - Checks the type of the object, returning true if - the object is a numeric type. - - The object to check - true if the object is a numeric type - - - - Checks the type of the object, returning true if - the object is a floating point numeric type. - - The object to check - true if the object is a floating point numeric type - - - - Checks the type of the object, returning true if - the object is a fixed point numeric type. - - The object to check - true if the object is a fixed point numeric type - - - - Test two numeric values for equality, performing the usual numeric - conversions and using a provided or default tolerance. If the tolerance - provided is Empty, this method may set it to a default tolerance. - - The expected value - The actual value - A reference to the tolerance in effect - True if the values are equal - - - - Compare two numeric values, performing the usual numeric conversions. - - The expected value - The actual value - The relationship of the values to each other - - - - NUnitComparer encapsulates NUnit's default behavior - in comparing two objects. - - - - - Compares two objects - - - - - - - - Returns the default NUnitComparer. - - - - - Generic version of NUnitComparer - - - - - - Compare two objects of the same type - - - - - NUnitEqualityComparer encapsulates NUnit's handling of - equality tests between objects. - - - - - - - - - - Compares two objects for equality within a tolerance - - The first object to compare - The second object to compare - The tolerance to use in the comparison - - - - - If true, all string comparisons will ignore case - - - - - If true, arrays will be treated as collections, allowing - those of different dimensions to be compared - - - - - Comparison objects used in comparisons for some constraints. - - - - - List of points at which a failure occured. - - - - - RecursionDetector used to check for recursion when - evaluating self-referencing enumerables. - - - - - Compares two objects for equality within a tolerance, setting - the tolerance to the actual tolerance used if an empty - tolerance is supplied. - - - - - Helper method to compare two arrays - - - - - Method to compare two DirectoryInfo objects - - first directory to compare - second directory to compare - true if equivalent, false if not - - - - Returns the default NUnitEqualityComparer - - - - - Gets and sets a flag indicating whether case should - be ignored in determining equality. - - - - - Gets and sets a flag indicating that arrays should be - compared as collections, without regard to their shape. - - - - - Gets the list of external comparers to be used to - test for equality. They are applied to members of - collections, in place of NUnit's own logic. - - - - - Gets the list of failure points for the last Match performed. - The list consists of objects to be interpreted by the caller. - This generally means that the caller may only make use of - objects it has placed on the list at a particular depthy. - - - - - RecursionDetector detects when a comparison - between two enumerables has reached a point - where the same objects that were previously - compared are again being compared. This allows - the caller to stop the comparison if desired. - - - - - Check whether two objects have previously - been compared, returning true if they have. - The two objects are remembered, so that a - second call will always return true. - - - - - OrConstraint succeeds if either member succeeds - - - - - Create an OrConstraint from two other constraints - - The first constraint - The second constraint - - - - Apply the member constraints to an actual value, succeeding - succeeding as soon as one of them succeeds. - - The actual value - True if either constraint succeeded - - - - Write a description for this contraint to a MessageWriter - - The MessageWriter to receive the description - - - - PathConstraint serves as the abstract base of constraints - that operate on paths and provides several helper methods. - - - - - The expected path used in the constraint - - - - - Flag indicating whether a caseInsensitive comparison should be made - - - - - Construct a PathConstraint for a give expected path - - The expected path - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Returns true if the expected path and actual path match - - - - - Returns the string representation of this constraint - - - - - Transform the provided path to its canonical form so that it - may be more easily be compared with other paths. - - The original path - The path in canonical form - - - - Test whether one path in canonical form is under another. - - The first path - supposed to be the parent path - The second path - supposed to be the child path - Indicates whether case should be ignored - - - - - Modifies the current instance to be case-insensitve - and returns it. - - - - - Modifies the current instance to be case-sensitve - and returns it. - - - - - Predicate constraint wraps a Predicate in a constraint, - returning success if the predicate is true. - - - - - Construct a PredicateConstraint from a predicate - - - - - Determines whether the predicate succeeds when applied - to the actual value. - - - - - Writes the description to a MessageWriter - - - - - PropertyConstraint extracts a named property and uses - its value as the actual value for a chained constraint. - - - - - Initializes a new instance of the class. - - The name. - The constraint to apply to the property. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a - MessageWriter. The default implementation simply writes - the raw value of actual, leaving it to the writer to - perform any formatting. - - The writer on which the actual value is displayed - - - - Returns the string representation of the constraint. - - - - - - PropertyExistsConstraint tests that a named property - exists on the object provided through Match. - - Originally, PropertyConstraint provided this feature - in addition to making optional tests on the vaue - of the property. The two constraints are now separate. - - - - - Initializes a new instance of the class. - - The name of the property. - - - - Test whether the property exists for a given object - - The object to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a - MessageWriter. - - The writer on which the actual value is displayed - - - - Returns the string representation of the constraint. - - - - - - RangeConstraint tests whether two values are within a - specified range. - - - - - Initializes a new instance of the class. - - From. - To. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - RegexConstraint can test whether a string matches - the pattern provided. - - - - - Initializes a new instance of the class. - - The pattern. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - ResolvableConstraintExpression is used to represent a compound - constraint being constructed at a point where the last operator - may either terminate the expression or may have additional - qualifying constraints added to it. - - It is used, for example, for a Property element or for - an Exception element, either of which may be optionally - followed by constraints that apply to the property or - exception. - - - - - Create a new instance of ResolvableConstraintExpression - - - - - Create a new instance of ResolvableConstraintExpression, - passing in a pre-populated ConstraintBuilder. - - - - - Resolve the current expression to a Constraint - - - - - This operator creates a constraint that is satisfied only if both - argument constraints are satisfied. - - - - - This operator creates a constraint that is satisfied only if both - argument constraints are satisfied. - - - - - This operator creates a constraint that is satisfied only if both - argument constraints are satisfied. - - - - - This operator creates a constraint that is satisfied if either - of the argument constraints is satisfied. - - - - - This operator creates a constraint that is satisfied if either - of the argument constraints is satisfied. - - - - - This operator creates a constraint that is satisfied if either - of the argument constraints is satisfied. - - - - - This operator creates a constraint that is satisfied if the - argument constraint is not satisfied. - - - - - Appends an And Operator to the expression - - - - - Appends an Or operator to the expression. - - - - - ReusableConstraint wraps a constraint expression after - resolving it so that it can be reused consistently. - - - - - Construct a ReusableConstraint from a constraint expression - - The expression to be resolved and reused - - - - Converts a constraint to a ReusableConstraint - - The constraint to be converted - A ReusableConstraint - - - - Returns the string representation of the constraint. - - A string representing the constraint - - - - Resolves the ReusableConstraint by returning the constraint - that it originally wrapped. - - A resolved constraint - - - - SameAsConstraint tests whether an object is identical to - the object passed to its constructor - - - - - Initializes a new instance of the class. - - The expected object. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Summary description for SamePathConstraint. - - - - - Initializes a new instance of the class. - - The expected path - - - - Test whether the constraint is satisfied by a given value - - The expected path - The actual path - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - SamePathOrUnderConstraint tests that one path is under another - - - - - Initializes a new instance of the class. - - The expected path - - - - Test whether the constraint is satisfied by a given value - - The expected path - The actual path - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - SomeItemsConstraint applies another constraint to each - item in a collection, succeeding if any of them succeeds. - - - - - Construct a SomeItemsConstraint on top of an existing constraint - - - - - - Apply the item constraint to each item in the collection, - succeeding if any item succeeds. - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - StartsWithConstraint can test whether a string starts - with an expected substring. - - - - - Initializes a new instance of the class. - - The expected string - - - - Test whether the constraint is matched by the actual value. - This is a template method, which calls the IsMatch method - of the derived class. - - - - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - SubPathConstraint tests that the actual path is under the expected path - - - - - Initializes a new instance of the class. - - The expected path - - - - Test whether the constraint is satisfied by a given value - - The expected path - The actual path - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - SubstringConstraint can test whether a string contains - the expected substring. - - - - - Initializes a new instance of the class. - - The expected. - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - ThrowsConstraint is used to test the exception thrown by - a delegate by applying a constraint to it. - - - - - Initializes a new instance of the class, - using a constraint to be applied to the exception. - - A constraint to apply to the caught exception. - - - - Executes the code of the delegate and captures any exception. - If a non-null base constraint was provided, it applies that - constraint to the exception. - - A delegate representing the code to be tested - True if an exception is thrown and the constraint succeeds, otherwise false - - - - Converts an ActualValueDelegate to a TestDelegate - before calling the primary overload. - - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a - MessageWriter. The default implementation simply writes - the raw value of actual, leaving it to the writer to - perform any formatting. - - The writer on which the actual value is displayed - - - - Returns the string representation of this constraint - - - - - Get the actual exception thrown - used by Assert.Throws. - - - - - ThrowsNothingConstraint tests that a delegate does not - throw an exception. - - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True if no exception is thrown, otherwise false - - - - Test whether the constraint is satisfied by a given delegate - - Delegate returning the value to be tested - True if no exception is thrown, otherwise false - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a - MessageWriter. Overridden in ThrowsNothingConstraint to write - information about the exception that was actually caught. - - The writer on which the actual value is displayed - - - - The Tolerance class generalizes the notion of a tolerance - within which an equality test succeeds. Normally, it is - used with numeric types, but it can be used with any - type that supports taking a difference between two - objects and comparing that difference to a value. - - - - - Constructs a linear tolerance of a specdified amount - - - - - Constructs a tolerance given an amount and ToleranceMode - - - - - Tests that the current Tolerance is linear with a - numeric value, throwing an exception if it is not. - - - - - Returns an empty Tolerance object, equivalent to - specifying no tolerance. In most cases, it results - in an exact match but for floats and doubles a - default tolerance may be used. - - - - - Returns a zero Tolerance object, equivalent to - specifying an exact match. - - - - - Gets the ToleranceMode for the current Tolerance - - - - - Gets the value of the current Tolerance instance. - - - - - Returns a new tolerance, using the current amount as a percentage. - - - - - Returns a new tolerance, using the current amount in Ulps. - - - - - Returns a new tolerance with a TimeSpan as the amount, using - the current amount as a number of days. - - - - - Returns a new tolerance with a TimeSpan as the amount, using - the current amount as a number of hours. - - - - - Returns a new tolerance with a TimeSpan as the amount, using - the current amount as a number of minutes. - - - - - Returns a new tolerance with a TimeSpan as the amount, using - the current amount as a number of seconds. - - - - - Returns a new tolerance with a TimeSpan as the amount, using - the current amount as a number of milliseconds. - - - - - Returns a new tolerance with a TimeSpan as the amount, using - the current amount as a number of clock ticks. - - - - - Returns true if the current tolerance is empty. - - - - - Modes in which the tolerance value for a comparison can be interpreted. - - - - - The tolerance was created with a value, without specifying - how the value would be used. This is used to prevent setting - the mode more than once and is generally changed to Linear - upon execution of the test. - - - - - The tolerance is used as a numeric range within which - two compared values are considered to be equal. - - - - - Interprets the tolerance as the percentage by which - the two compared values my deviate from each other. - - - - - Compares two values based in their distance in - representable numbers. - - - - - TrueConstraint tests that the actual value is true - - - - - Initializes a new instance of the class. - - - - - UniqueItemsConstraint tests whether all the items in a - collection are unique. - - - - - Check that all items are unique. - - - - - - - Write a description of this constraint to a MessageWriter - - - - - - XmlSerializableConstraint tests whether - an object is serializable in XML format. - - - - - Test whether the constraint is satisfied by a given value - - The value to be tested - True for success, false for failure - - - - Write the constraint description to a MessageWriter - - The writer on which the description is displayed - - - - Write the actual value for a failing constraint test to a - MessageWriter. The default implementation simply writes - the raw value of actual, leaving it to the writer to - perform any formatting. - - The writer on which the actual value is displayed - - - - Returns the string representation of this constraint - - - - - Represents a constraint that succeeds if all the - members of a collection match a base constraint. - - - - - Abstract base for operators that indicate how to - apply a constraint to items in a collection. - - - - - PrefixOperator takes a single constraint and modifies - it's action in some way. - - - - - The ConstraintOperator class is used internally by a - ConstraintBuilder to represent an operator that - modifies or combines constraints. - - Constraint operators use left and right precedence - values to determine whether the top operator on the - stack should be reduced before pushing a new operator. - - - - - The precedence value used when the operator - is about to be pushed to the stack. - - - - - The precedence value used when the operator - is on the top of the stack. - - - - - Reduce produces a constraint from the operator and - any arguments. It takes the arguments from the constraint - stack and pushes the resulting constraint on it. - - - - - - The syntax element preceding this operator - - - - - The syntax element folowing this operator - - - - - The precedence value used when the operator - is about to be pushed to the stack. - - - - - The precedence value used when the operator - is on the top of the stack. - - - - - Reduce produces a constraint from the operator and - any arguments. It takes the arguments from the constraint - stack and pushes the resulting constraint on it. - - - - - - Returns the constraint created by applying this - prefix to another constraint. - - - - - - - Constructs a CollectionOperator - - - - - Returns a constraint that will apply the argument - to the members of a collection, succeeding if - they all succeed. - - - - - Operator that requires both it's arguments to succeed - - - - - Abstract base class for all binary operators - - - - - Reduce produces a constraint from the operator and - any arguments. It takes the arguments from the constraint - stack and pushes the resulting constraint on it. - - - - - - Abstract method that produces a constraint by applying - the operator to its left and right constraint arguments. - - - - - Gets the left precedence of the operator - - - - - Gets the right precedence of the operator - - - - - Construct an AndOperator - - - - - Apply the operator to produce an AndConstraint - - - - - Operator that tests for the presence of a particular attribute - on a type and optionally applies further tests to the attribute. - - - - - Abstract base class for operators that are able to reduce to a - constraint whether or not another syntactic element follows. - - - - - Construct an AttributeOperator for a particular Type - - The Type of attribute tested - - - - Reduce produces a constraint from the operator and - any arguments. It takes the arguments from the constraint - stack and pushes the resulting constraint on it. - - - - - Represents a constraint that succeeds if the specified - count of members of a collection match a base constraint. - - - - - Construct an ExactCountOperator for a specified count - - The expected count - - - - Returns a constraint that will apply the argument - to the members of a collection, succeeding if - none of them succeed. - - - - - Represents a constraint that succeeds if none of the - members of a collection match a base constraint. - - - - - Returns a constraint that will apply the argument - to the members of a collection, succeeding if - none of them succeed. - - - - - Negates the test of the constraint it wraps. - - - - - Constructs a new NotOperator - - - - - Returns a NotConstraint applied to its argument. - - - - - Operator that requires at least one of it's arguments to succeed - - - - - Construct an OrOperator - - - - - Apply the operator to produce an OrConstraint - - - - - Operator used to test for the presence of a named Property - on an object and optionally apply further tests to the - value of that property. - - - - - Constructs a PropOperator for a particular named property - - - - - Reduce produces a constraint from the operator and - any arguments. It takes the arguments from the constraint - stack and pushes the resulting constraint on it. - - - - - - Gets the name of the property to which the operator applies - - - - - Represents a constraint that succeeds if any of the - members of a collection match a base constraint. - - - - - Returns a constraint that will apply the argument - to the members of a collection, succeeding if - any of them succeed. - - - - - Operator that tests that an exception is thrown and - optionally applies further tests to the exception. - - - - - Construct a ThrowsOperator - - - - - Reduce produces a constraint from the operator and - any arguments. It takes the arguments from the constraint - stack and pushes the resulting constraint on it. - - - - - Represents a constraint that simply wraps the - constraint provided as an argument, without any - further functionality, but which modifes the - order of evaluation because of its precedence. - - - - - Constructor for the WithOperator - - - - - Returns a constraint that wraps its argument - - - - - Thrown when an assertion failed. - - - - The error message that explains - the reason for the exception - - - The error message that explains - the reason for the exception - The exception that caused the - current exception - - - - Serialization Constructor - - - - - Thrown when an assertion failed. - - - - - - - The error message that explains - the reason for the exception - The exception that caused the - current exception - - - - Serialization Constructor - - - - - Thrown when a test executes inconclusively. - - - - The error message that explains - the reason for the exception - - - The error message that explains - the reason for the exception - The exception that caused the - current exception - - - - Serialization Constructor - - - - - Thrown when an assertion failed. - - - - - - - The error message that explains - the reason for the exception - The exception that caused the - current exception - - - - Serialization Constructor - - - - - - - - - - - Compares two objects of a given Type for equality within a tolerance - - The first object to compare - The second object to compare - The tolerance to use in the comparison - - - - diff --git a/HandsetDetectionAPIKit4/obj/Debug/Web.dll b/HandsetDetectionAPIKit4/obj/Debug/Web.dll deleted file mode 100644 index 80f70f7950a03c31dc0cb5dbaa9d938c99298f38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9728 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 Date: Thu, 4 Feb 2016 16:35:50 +0530 Subject: [PATCH 2/5] Changes --- HandsetDetectionAPI/HD4.cs | 219 ++++---- HandsetDetectionAPI/HDBase.cs | 324 ++++++------ HandsetDetectionAPI/HDCache.cs | 49 +- HandsetDetectionAPI/HDDevice.cs | 494 ++++++++---------- HandsetDetectionAPI/HDExtra.cs | 148 +++--- HandsetDetectionAPI/HDStore.cs | 124 ++--- HandsetDetectionAPI/HandsetDetectionType.cs | 4 +- HandsetDetectionAPI/testHD4.cs | 345 ++++++------ HandsetDetectionAPI/testHDCache.cs | 32 +- HandsetDetectionAPI/testHDDevice.cs | 42 +- HandsetDetectionAPI/testHDStore.cs | 102 ++-- HandsetDetectionAPIKit4/Benchmark.aspx.cs | 6 +- HandsetDetectionAPIKit4/Default.aspx.cs | 9 +- .../HandsetWithNetwork.aspx.cs | 22 +- HandsetDetectionAPIKit4/Models.aspx.cs | 22 +- .../ModelsProperties.aspx.cs | 22 +- HandsetDetectionAPIKit4/SimpleDetect.aspx.cs | 16 +- HandsetDetectionAPIKit4/Vendors.aspx.cs | 22 +- 18 files changed, 941 insertions(+), 1061 deletions(-) diff --git a/HandsetDetectionAPI/HD4.cs b/HandsetDetectionAPI/HD4.cs index ced41518..b04310dd 100644 --- a/HandsetDetectionAPI/HD4.cs +++ b/HandsetDetectionAPI/HD4.cs @@ -2,28 +2,26 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Collections.Specialized; using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; -using System.Threading.Tasks; using System.Web; using System.Web.Script.Serialization; namespace HandsetDetectionAPI { - public class HD4 : HDBase + public class Hd4 : HdBase { public bool UseLocal { get { - return Convert.ToBoolean(config["use_local"]); + return Convert.ToBoolean(Config["use_local"]); } set { - config["use_local"] = value.ToString(); + Config["use_local"] = value.ToString(); } } @@ -31,38 +29,35 @@ public bool Geoip { get { - return Convert.ToBoolean(config["geoip"]); + return Convert.ToBoolean(Config["geoip"]); } set { - config["geoip"] = value.ToString(); + Config["geoip"] = value.ToString(); } } + string _configFile = "/hdUltimateConfig.json"; - - bool debug = true; - string configFile = "/hdUltimateConfig.json"; - - HDStore Store; - HDCache cache = null; - HDDevice device = null; - private HttpRequest Request; - public void cleanUp() { rawreply = ""; reply = new Dictionary(); } - public string getLog() { return this.log; } - public string getError() { return this.error; } + HdStore _store; + HdCache _cache = null; + HdDevice _device = null; + private HttpRequest _request; + public void CleanUp() { Rawreply = ""; Reply = new Dictionary(); } + public string GetLog() { return Log; } + public string GetError() { return Error; } private void AddKey(string key, string value) { key = key.ToLower(); - if (detectRequest.ContainsKey(key)) + if (DetectRequest.ContainsKey(key)) { - this.detectRequest.Remove(key); + DetectRequest.Remove(key); } - this.detectRequest.Add(key, value); + DetectRequest.Add(key, value); } /// @@ -70,20 +65,20 @@ private void AddKey(string key, string value) /// /// Curret Request Object /// config can be an array of config options or a fully qualified path to an alternate config file. - public HD4(HttpRequest request, dynamic configuration = null) + public Hd4(HttpRequest request, dynamic configuration = null) { - this.Request = request; + _request = request; if (configuration != null && configuration is IDictionary) { - foreach (var item in (Dictionary)configuration) + foreach (KeyValuePair item in (Dictionary)configuration) { - if (config.ContainsKey(item.Key)) + if (Config.ContainsKey(item.Key)) { - config[item.Key] = item.Value; + Config[item.Key] = item.Value; } else { - config.Add(item.Key, item.Value); + Config.Add(item.Key, item.Value); } } } @@ -91,24 +86,22 @@ public HD4(HttpRequest request, dynamic configuration = null) { AddConfigSettingFromFile(ApplicationRootDirectory + configuration); } - else if (!File.Exists(ApplicationRootDirectory + configFile)) + else if (!File.Exists(ApplicationRootDirectory + _configFile)) { throw new Exception("Error : Invalid config file and no config passed to constructor"); } else { - AddConfigSettingFromFile(ApplicationRootDirectory + configFile); + AddConfigSettingFromFile(ApplicationRootDirectory + _configFile); } - this.debug = Debug; - - this.Store = HDStore.Instance; - this.Store.setPath(config["filesdir"], true); + _store = HdStore.Instance; + _store.SetPath(Config["filesdir"], true); - this.cache = new HDCache(); - this.device = new HDDevice(); + _cache = new HdCache(); + _device = new HdDevice(); - this.setup(); + Setup(); } /// @@ -119,19 +112,19 @@ private void AddConfigSettingFromFile(string configFile) { Dictionary hdConfig = new Dictionary(); - var serializer = new JavaScriptSerializer(); - string jsonText = System.IO.File.ReadAllText(configFile); + JavaScriptSerializer serializer = new JavaScriptSerializer(); + string jsonText = File.ReadAllText(configFile); hdConfig = serializer.Deserialize>(jsonText); - foreach (var item in hdConfig) + foreach (KeyValuePair item in hdConfig) { - if (config.ContainsKey(item.Key)) + if (Config.ContainsKey(item.Key)) { - config[item.Key] = item.Value; + Config[item.Key] = item.Value; } else { - config.Add(item.Key, item.Value); + Config.Add(item.Key, item.Value); } } } @@ -139,37 +132,37 @@ private void AddConfigSettingFromFile(string configFile) /// /// Initialize inital properties /// - void setup() + void Setup() { - reply = new Dictionary(); - rawReply = new Dictionary(); - detectRequest = new Dictionary(); + Reply = new Dictionary(); + RawReply = new Dictionary(); + DetectRequest = new Dictionary(); Regex reg = new Regex("^x|^http", RegexOptions.IgnoreCase); - foreach (string header in Request.Headers) + foreach (string header in _request.Headers) { if (reg.IsMatch(header)) { - AddKey(header.ToLower(), Request[header]); + AddKey(header.ToLower(), _request[header]); } } - AddKey("user-agent", Request.UserAgent); - AddKey("ipaddress", Request.UserHostAddress); - AddKey("request_uri", Request.Url.ToString()); + AddKey("user-agent", _request.UserAgent); + AddKey("ipaddress", _request.UserHostAddress); + AddKey("request_uri", _request.Url.ToString()); if (!UseLocal && Geoip) { // Ip address only used in cloud mode - this.detectRequest["ipaddress"] = this.Request.ServerVariables["REMOTE_ADDR"] != null ? this.Request.ServerVariables["REMOTE_ADDR"] : null; + DetectRequest["ipaddress"] = _request.ServerVariables["REMOTE_ADDR"] != null ? _request.ServerVariables["REMOTE_ADDR"] : null; } - detectRequest["Cookie"] = null; + DetectRequest["Cookie"] = null; } /// /// List all known vendors /// /// true on success, false otherwise. Use getRawReply to inspect results on success. - public bool deviceVendors() + public bool DeviceVendors() { // resetLog(); try @@ -177,7 +170,7 @@ public bool deviceVendors() if (UseLocal) { - return device.localDeviceVendors(); + return _device.LocalDeviceVendors(); } else { @@ -186,7 +179,7 @@ public bool deviceVendors() } catch (Exception ex) { - this.setError(299, "Exception : " + ex.Message + " " + ex.StackTrace); + SetError(299, "Exception : " + ex.Message + " " + ex.StackTrace); return false; } } @@ -196,14 +189,14 @@ public bool deviceVendors() /// /// vendor The device vendor eg Apple /// true on success, false otherwise. Use getRawReply to inspect results on success - public bool deviceModels(string vendor) + public bool DeviceModels(string vendor) { // resetLog(); try { if (UseLocal) { - return device.localDeviceModels(vendor); + return _device.LocalDeviceModels(vendor); } else { @@ -212,7 +205,7 @@ public bool deviceModels(string vendor) } catch (Exception ex) { - this.setError(299, "Exception : " + ex.Message + " " + ex.StackTrace); + SetError(299, "Exception : " + ex.Message + " " + ex.StackTrace); return false; } } @@ -223,13 +216,13 @@ public bool deviceModels(string vendor) /// vendor The device vendor eg. Nokia /// model The deviec model eg. N95 /// true on success, false otherwise. Use getReply to inspect results on success - public bool deviceView(string vendor, string model) + public bool DeviceView(string vendor, string model) { try { if (UseLocal) { - return device.localDeviceView(vendor, model); + return _device.LocalDeviceView(vendor, model); } else { @@ -238,7 +231,7 @@ public bool deviceView(string vendor, string model) } catch (Exception ex) { - this.setError(299, "Exception : " + ex.Message + " " + ex.StackTrace); + SetError(299, "Exception : " + ex.Message + " " + ex.StackTrace); return false; } } @@ -249,13 +242,13 @@ public bool deviceView(string vendor, string model) /// Property to inquire about eg 'network', 'connectors' etc... /// true on success, false otherwise. Use getReply to inspect results on success. /// - public bool deviceWhatHas(string key, string value) + public bool DeviceWhatHas(string key, string value) { try { if (UseLocal) { - return device.localWhatHas(key, value); + return _device.LocalWhatHas(key, value); } else { @@ -264,7 +257,7 @@ public bool deviceWhatHas(string key, string value) } catch (Exception ex) { - this.setError(299, "Exception : " + ex.Message + " " + ex.StackTrace); + SetError(299, "Exception : " + ex.Message + " " + ex.StackTrace); return false; } } @@ -274,12 +267,12 @@ public bool deviceWhatHas(string key, string value) /// /// Data for device detection : HTTP Headers usually /// true on success, false otherwise. Use getReply to inspect results on success. - public bool deviceDetect(Dictionary data = null) + public bool DeviceDetect(Dictionary data = null) { int id = 0; - if (data == null || data.Count() == 0 || !data.ContainsKey("id")) + if (data == null || !data.Any() || !data.ContainsKey("id")) { - id = Convert.ToInt32(config["site_id"]); + id = Convert.ToInt32(Config["site_id"]); } else { @@ -287,7 +280,7 @@ public bool deviceDetect(Dictionary data = null) } Dictionary requestBody = new Dictionary(); - foreach (var item in data) + foreach (KeyValuePair item in data) { if (requestBody.ContainsKey(item.Key.ToLower())) { @@ -305,35 +298,39 @@ public bool deviceDetect(Dictionary data = null) // If caching enabled then check cache if (Cacherequests) { - var headersKeys = requestBody.Values.Select(c => c).OrderBy(c => c); - var serializer = new JavaScriptSerializer(); - fastKey = serializer.Serialize(headersKeys).Replace(" ", ""); - var objReply = this.cache.read(fastKey); + IOrderedEnumerable headersKeys = requestBody.Values.Select(c => c).OrderBy(c => c); + fastKey = Jss.Serialize(headersKeys).Replace(" ", ""); + Dictionary objReply = _cache.Read(fastKey); if (objReply.Count > 0) { - reply = objReply; - setRawReply(); - return setError(0, "OK"); + Reply = objReply; + SetRawReply(); + return SetError(0, "OK"); } } try { + bool result = false; if (UseLocal) { - var result = device.localDetect(requestBody); + result = _device.LocalDetect(requestBody); // Log unknown headers if enabled - setError(device.getStatus(), device.getMessage()); - return result; + SetError(_device.GetStatus(), _device.GetMessage()); } else { - return Remote(string.Format("/device/detect/{0}", id.ToString()), requestBody); + result = Remote(string.Format("/device/detect/{0}", id), requestBody); + } + if (Cacherequests) + { + _cache.Write(fastKey, GetReply()); } + return result; } catch (Exception ex) { - this.setError(299, "Exception : " + ex.Message + " " + ex.StackTrace); + SetError(299, "Exception : " + ex.Message + " " + ex.StackTrace); return false; } } @@ -342,51 +339,51 @@ public bool deviceDetect(Dictionary data = null) /// Fetch an archive from handset detection which contains all the device specs and matching trees as individual json files. /// /// hd_specs data on success, false otherwise - public dynamic deviceFetchArchive() + public dynamic DeviceFetchArchive() { - this.isDownloadableFiles = true; - if (!this.Remote("device/fetcharchive", null, "zip")) + IsDownloadableFiles = true; + if (!Remote("device/fetcharchive", null, "zip")) return false; - var data = this.getRawReply(); + string data = GetRawReply(); - if (data.Count() == 0) - return this.setError(299, "Error : FetchArchive failed. Bad Download. File is zero length"); + if (!data.Any()) + return SetError(299, "Error : FetchArchive failed. Bad Download. File is zero length"); else if (data.Length < 9000000) { - var serializer = new JavaScriptSerializer(); - var trythis = serializer.Deserialize>(data); + JavaScriptSerializer serializer = new JavaScriptSerializer(); + Dictionary trythis = serializer.Deserialize>(data); if (trythis.Count > 0 && trythis.ContainsKey("status") && trythis.ContainsKey("message")) - return setError(Convert.ToInt32(trythis["status"]), trythis["message"]); + return SetError(Convert.ToInt32(trythis["status"]), trythis["message"]); } - return installArchive(config["filesdir"], "ultimate.zip"); + return installArchive(Config["filesdir"], "ultimate.zip"); } /// /// Community Fetch Archive - Fetch the community archive version /// /// hd_specs data on success, false otherwise - public dynamic communityFetchArchive() + public dynamic CommunityFetchArchive() { - this.isDownloadableFiles = true; - if (!this.Remote("community/fetcharchive", null, "zip", false)) + IsDownloadableFiles = true; + if (!Remote("community/fetcharchive", null, "zip", false)) return false; - var data = this.getRawReply(); + string data = GetRawReply(); if (string.IsNullOrEmpty(data)) - return setError(299, "Error : FetchArchive failed. Bad Download. File is zero length"); + return SetError(299, "Error : FetchArchive failed. Bad Download. File is zero length"); else if (data.Length < 900000) { - var serializer = new JavaScriptSerializer(); - var trythis = serializer.Deserialize>(data); + JavaScriptSerializer serializer = new JavaScriptSerializer(); + Dictionary trythis = serializer.Deserialize>(data); if (trythis.Count > 0 && trythis.ContainsKey("status") && trythis.ContainsKey("message")) - return setError(Convert.ToInt32(trythis["status"]), trythis["message"]); + return SetError(Convert.ToInt32(trythis["status"]), trythis["message"]); } - return installArchive(config["filesdir"], "communityTest.zip"); + return installArchive(Config["filesdir"], "communityTest.zip"); } /// @@ -402,9 +399,9 @@ public bool installArchive(string directoryPath, string fileName) } else { - var directoryArray = directoryPath.Replace("/", "\\").Split(new String[] { "\\" }, StringSplitOptions.RemoveEmptyEntries).ToList(); - var directoryString = ""; - foreach (var item in directoryArray) + List directoryArray = directoryPath.Replace("/", "\\").Split(new String[] { "\\" }, StringSplitOptions.RemoveEmptyEntries).ToList(); + string directoryString = ""; + foreach (string item in directoryArray) { directoryString += item + "\\"; if (DriveInfo.GetDrives().Any(drive => drive.Name.ToLower() == directoryString)) @@ -421,7 +418,7 @@ public bool installArchive(string directoryPath, string fileName) } } - fileName = config["filesdir"] + "\\" + fileName; + fileName = Config["filesdir"] + "\\" + fileName; // responseStream.Close(); return installArchive(fileName); @@ -434,23 +431,23 @@ public bool installArchive(string filePath) int c = 1; while (c > 0) { - c = reader.Read(buff, 0, 1024); + c = Reader.Read(buff, 0, 1024); for (int i = 0; i < c; i++) bw.Write(buff[i]); } bw.Close(); - var directoryPath = filePath.Substring(0, filePath.LastIndexOf("\\")); + string directoryPath = filePath.Substring(0, filePath.LastIndexOf("\\")); - if (!directoryPath.Contains(Store.dirname)) + if (!directoryPath.Contains(_store.Dirname)) { - directoryPath += "\\" + Store.dirname; + directoryPath += "\\" + _store.Dirname; } using (ZipFile zip = ZipFile.Read(filePath)) { zip.ToList().ForEach(entry => { - entry.FileName = System.IO.Path.GetFileName(entry.FileName.Replace(':', '_')); + entry.FileName = Path.GetFileName(entry.FileName.Replace(':', '_')); entry.Extract(directoryPath, ExtractExistingFileAction.OverwriteSilently); }); } @@ -462,9 +459,9 @@ public bool installArchive(string filePath) /// /// headers /// true if helpful, false otherwise. - public bool isHelperUseful(Dictionary headers) + public bool IsHelperUseful(Dictionary headers) { - return device.isHelperUseful(headers); + return _device.IsHelperUseful(headers); } } } diff --git a/HandsetDetectionAPI/HDBase.cs b/HandsetDetectionAPI/HDBase.cs index 635948cb..57a2fdcc 100644 --- a/HandsetDetectionAPI/HDBase.cs +++ b/HandsetDetectionAPI/HDBase.cs @@ -13,9 +13,13 @@ namespace HandsetDetectionAPI { //#define DEBUG = 0 - public class HDBase + public class HdBase { - protected static Dictionary config = new Dictionary() {{"username", ""}, + public static int MaxJsonLength = 40000000; + + protected static JavaScriptSerializer Jss = new JavaScriptSerializer { MaxJsonLength = MaxJsonLength }; + + protected static Dictionary Config = new Dictionary() {{"username", ""}, {"secret", ""}, {"site_id", ""}, {"mobile_site", ""}, @@ -33,14 +37,14 @@ public class HDBase {"cache_requests", true}, {"geoip", false}, {"log_unknown", true }}; - protected Dictionary detectedRuleKey = new Dictionary(); - string apiBase = "/apiv4/"; - string deviceUAFilter = " _\\#-,./:\"'"; - string extraUAFilter = " "; + protected Dictionary DetectedRuleKey = new Dictionary(); + string _apiBase = "/apiv4/"; + string _deviceUaFilter = " _\\#-,./:\"'"; + string _extraUaFilter = " "; //string loggerHost = "logger.handsetdetection.com"; //int loggerPort = 80; - protected Dictionary detectionConfig + protected Dictionary DetectionConfig { get { @@ -62,10 +66,10 @@ protected Dictionary detectionConfig dicDeviceBiOrder.Add("android", dicAndroid); - List> dicIOS = new List>(); - dicIOS.Add(new List() { "utsname.brand", "utsname.machine" }); + List> dicIos = new List>(); + dicIos.Add(new List() { "utsname.brand", "utsname.machine" }); - dicDeviceBiOrder.Add("ios", dicIOS); + dicDeviceBiOrder.Add("ios", dicIos); List> dicWindowPhone = new List>(); dicWindowPhone.Add(new List() { "devicemanufacturer", "devicename" }); @@ -81,10 +85,10 @@ protected Dictionary detectionConfig dicPlatformBiOrder.Add("android", dicPlatformAndroid); - List> dicPlatformIOS = new List>(); - dicPlatformIOS.Add(new List() { "uidevice.systemName", "uidevice.systemversion" }); + List> dicPlatformIos = new List>(); + dicPlatformIos.Add(new List() { "uidevice.systemName", "uidevice.systemversion" }); - dicPlatformBiOrder.Add("ios", dicPlatformIOS); + dicPlatformBiOrder.Add("ios", dicPlatformIos); List> dicPlatformWindowPhone = new List>(); @@ -106,45 +110,44 @@ protected Dictionary detectionConfig /// /// Getting languages list from Languages.json file /// - public Dictionary detectionLanguages + public Dictionary DetectionLanguages { get { - var serializer = new JavaScriptSerializer(); + JavaScriptSerializer serializer = new JavaScriptSerializer(); string jsonText = System.IO.File.ReadAllText(ApplicationRootDirectory + "\\Languages.json"); return serializer.Deserialize>(jsonText); } } - protected static Dictionary reply = null; + protected static Dictionary Reply = null; - public HDBase() + public HdBase() { - deviceUAFilterList = deviceUAFilter.Split(new String[] { "//" }, StringSplitOptions.RemoveEmptyEntries).ToList(); - extraUAFilterList = extraUAFilter.Split(new String[] { "//" }, StringSplitOptions.RemoveEmptyEntries).ToList(); + DeviceUaFilterList = _deviceUaFilter.Split(new String[] { "//" }, StringSplitOptions.RemoveEmptyEntries).ToList(); + ExtraUaFilterList = _extraUaFilter.Split(new String[] { "//" }, StringSplitOptions.RemoveEmptyEntries).ToList(); ReadTimeout = 120; - Store = HDStore.Instance; + _store = HdStore.Instance; } /// /// Get reply status /// /// int error status, 0 is Ok, anything else is probably not Ok - public int getStatus() + public int GetStatus() { - if (reply.ContainsKey("status")) - return Convert.ToInt32(reply["status"]); - else + if (!Reply.ContainsKey("status")) return 301; + return Convert.ToInt32(Reply["status"]); } /// /// Get reply message /// /// string A message - public string getMessage() + public string GetMessage() { - if (reply.ContainsKey("status")) - return reply["message"]; + if (Reply.ContainsKey("status")) + return Reply["message"]; else return "Not Found"; } @@ -153,18 +156,18 @@ public string getMessage() /// Get reply payload in array assoc format /// /// - public Dictionary getReply() + public Dictionary GetReply() { - return reply; + return Reply; } /// /// Set a reply payload /// /// - public void setReply(Dictionary objReply) + public void SetReply(Dictionary objReply) { - reply = objReply; + Reply = objReply; } /// @@ -173,12 +176,12 @@ public void setReply(Dictionary objReply) /// /// /// true if no error, or false otherwise. - protected bool setError(int status, string msg) + protected bool SetError(int status, string msg) { - this.error = msg; - reply["status"] = status; - reply["message"] = msg; - return (status > 0 ? false : true); + this.Error = msg; + Reply["status"] = status; + Reply["message"] = msg; + return (status <= 0); } /// @@ -186,42 +189,43 @@ protected bool setError(int status, string msg) /// /// /// string Cleansed string - public string extraCleanStr(string str) + public string ExtraCleanStr(string str) { if (string.IsNullOrEmpty(str)) return string.Empty; - foreach (string item in extraUAFilterList) + for (int i = 0; i < ExtraUaFilterList.Count; i++) { - foreach (var itemChar in item) + for (int j = 0; j < ExtraUaFilterList[i].Length; j++) { - str = str.Replace(itemChar, ' '); + str = str.Replace(ExtraUaFilterList[i][j], ' '); } } - Regex reg = new Regex("[^(\x20-\x7F)]*"); - str = reg.Replace(str, ""); + + str = _reg.Replace(str, ""); return Regex.Replace(str, @"\s+", ""); } + static Regex _reg = new Regex("[^(\x20-\x7F)]*", RegexOptions.Compiled); /// /// Standard string cleanse for device matching /// /// /// string cleansed string - public string cleanStr(string str) + public string CleanStr(string str) { if (string.IsNullOrEmpty(str)) return string.Empty; - foreach (string item in deviceUAFilterList) + + for (int i = 0; i < DeviceUaFilterList.Count; i++) { - foreach (var itemChar in item) + for (int j = 0; j < DeviceUaFilterList[i].Length; j++) { - str = str.Replace(itemChar, ' '); + str = str.Replace(DeviceUaFilterList[i][j], ' '); } - } - Regex reg = new Regex("[^(\x20-\x7F)]*"); - str = reg.Replace(str, ""); + + str = _reg.Replace(str, ""); return Regex.Replace(str, @"\s+", ""); } @@ -233,21 +237,18 @@ public string cleanStr(string str) /// JsonData protected bool Remote(string suburl, Dictionary data, string filetype = "json", bool authRequired = true) { - reply = new Dictionary(); - this.rawReply = new Dictionary(); - this.setError(0, "OK"); - - var jss = new JavaScriptSerializer(); - jss.MaxJsonLength = this.maxJsonLength; + Reply = new Dictionary(); + this.RawReply = new Dictionary(); + this.SetError(0, "OK"); string request; - string requestUrl = apiBase + suburl; - int attempts = config["retries"] + 1; + string requestUrl = _apiBase + suburl; + int attempts = Config["retries"] + 1; int trys = 0; if (data == null || data.Count == 0) request = ""; else - request = jss.Serialize(data); + request = Jss.Serialize(data); bool status = false; bool success = false; @@ -257,23 +258,23 @@ protected bool Remote(string suburl, Dictionary data, string fi { while (trys++ < attempts && success == false) { - status = post(config["api_server"], requestUrl, request, authRequired); + status = Post(Config["api_server"], requestUrl, request, authRequired); if (status) { - reply = jss.Deserialize>(rawreply); + Reply = Jss.Deserialize>(Rawreply); if (filetype.ToLower() == "json") { - if (reply.Count == 0) + if (Reply.Count == 0) { - setError(299, "Error: Empty Reply."); + SetError(299, "Error: Empty Reply."); } - else if (!reply.ContainsKey("status")) + else if (!Reply.ContainsKey("status")) { - setError(299, "Error : No status set in reply"); + SetError(299, "Error : No status set in reply"); } - else if (Convert.ToInt32(reply["status"]) != 0) + else if (Convert.ToInt32(Reply["status"]) != 0) { - setError(reply["status"], reply["message"]); + SetError(Reply["status"], Reply["message"]); trys = attempts + 1; } else @@ -291,7 +292,7 @@ protected bool Remote(string suburl, Dictionary data, string fi } catch (Exception ex) { - this.setError(299, "Exception : " + ex.Message + " " + ex.StackTrace); + this.SetError(299, "Exception : " + ex.Message + " " + ex.StackTrace); } return success; } @@ -304,7 +305,7 @@ protected bool Remote(string suburl, Dictionary data, string fi /// Data in json format /// Is authentication reguired /// false on failue (sets error), or string on success. - private bool post(string server, string service, string jsondata, bool authRequired = true) + private bool Post(string server, string service, string jsondata, bool authRequired = true) { try { @@ -353,20 +354,20 @@ private bool post(string server, string service, string jsondata, bool authRequi Stream dataStream = req.GetRequestStream(); dataStream.Write(payload, 0, payload.Length); dataStream.Close(); - var httpResponse = (HttpWebResponse)req.GetResponse(); - responseStream = new MemoryStream(); - responseStream = httpResponse.GetResponseStream(); - reader = new BinaryReader(responseStream); + HttpWebResponse httpResponse = (HttpWebResponse)req.GetResponse(); + _responseStream = new MemoryStream(); + _responseStream = httpResponse.GetResponseStream(); + Reader = new BinaryReader(_responseStream); if (httpResponse.StatusCode == HttpStatusCode.OK) { - if (this.isDownloadableFiles) + if (this.IsDownloadableFiles) { - rawreply = "{\"status\":0}"; + Rawreply = "{\"status\":0}"; } else { - rawreply = new StreamReader(responseStream).ReadToEnd(); + Rawreply = new StreamReader(_responseStream).ReadToEnd(); } return true; } @@ -374,7 +375,7 @@ private bool post(string server, string service, string jsondata, bool authRequi } catch (Exception ex) { - this.setError(299, "Exception : " + ex.Message + " " + ex.StackTrace); + this.SetError(299, "Exception : " + ex.Message + " " + ex.StackTrace); } return false; } @@ -384,9 +385,9 @@ private bool post(string server, string service, string jsondata, bool authRequi /// /// /// platform name on success, false otherwise - public dynamic hasBiKeys(Dictionary headers) + public dynamic HasBiKeys(Dictionary headers) { - Dictionary biKeys = detectionConfig["device-bi-order"]; + Dictionary biKeys = DetectionConfig["device-bi-order"]; List dataKeys = headers.Select(c => c.Key.ToLower()).ToList(); // Fast check @@ -400,18 +401,17 @@ public dynamic hasBiKeys(Dictionary headers) return false; } - int count = 0; - int total = 0; foreach (KeyValuePair platform in biKeys) { List> set = platform.Value; - foreach (var tuple in set) + for (int i = 0; i < set.Count; i++) { - List tupleSet = tuple; - count = 0; - total = tupleSet.Count(); - foreach (var item in tupleSet) + List tupleSet = set[i]; + int count = 0; + int total = tupleSet.Count(); + for (int index = 0; index < tupleSet.Count; index++) { + string item = tupleSet[index]; if (dataKeys.Contains(item)) { count++; @@ -421,7 +421,6 @@ public dynamic hasBiKeys(Dictionary headers) return platform; } } - } return false; } @@ -435,66 +434,54 @@ public dynamic hasBiKeys(Dictionary headers) /// /// /// node (which is an id) on success, false otherwise - public dynamic getMatch(string header, string value, string subtree = "0", string actualHeader = "", string className = "device") + public dynamic GetMatch(string header, string value, string subtree = "0", string actualHeader = "", string className = "device") { - int f = 0; - int r = 0; - string treetag; + //int f = 0; + //int r = 0; + string branchName; value = value.ToLower(); - if (className.ToLower() == "device") + if (string.Compare(className, "device", StringComparison.OrdinalIgnoreCase) == 0) { - value = cleanStr(value); - treetag = header + subtree; + value = CleanStr(value); + branchName = header + subtree; } else { - value = extraCleanStr(value); - treetag = header + subtree; + value = ExtraCleanStr(value); + branchName = header + subtree; } if (string.IsNullOrEmpty(value) || value.Length < 4) { return false; } - Dictionary branch = getBranch(treetag); - string node = string.Empty; + Dictionary branch = GetBranch(branchName); + if (branch == null) { return false; } - if (header.ToLower() == "user-agent") + if (string.Compare(header, "user-agent", StringComparison.OrdinalIgnoreCase) == 0) { - foreach (var order in branch) + foreach (KeyValuePair filter in branch.Select(order => order.Value).OfType>().SelectMany(filters => filters)) { - Dictionary filters = order.Value; - foreach (var filter in filters) + // ++f; + if (!value.Contains(filter.Key)) continue; + + Dictionary matches = (Dictionary)filter.Value; + foreach (KeyValuePair match in matches.Where(match => value.Contains(match.Key))) { - ++f; - Dictionary matches = filter.Value; - if (value.Contains(filter.Key)) - { - foreach (var match in matches) - { - ++r; - if (value.Contains(match.Key)) - { - detectedRuleKey[className] = cleanStr(header) + ":" + cleanStr(filter.Key) + ":" + cleanStr(match.Key); - return match.Value; - } - } - } + DetectedRuleKey[className] = CleanStr(header) + ":" + CleanStr(filter.Key) + ":" + CleanStr(match.Key); + return match.Value; } } } else { - if (branch.ContainsKey(value)) - { - node = branch[value]; - return node; - } + if (branch.ContainsKey(value)) return branch[value]; + return false; } @@ -506,20 +493,18 @@ public dynamic getMatch(string header, string value, string subtree = "0", strin /// /// The name of the branch to find /// an assoc array on success, false otherwise. - public Dictionary getBranch(string branchName) + public Dictionary GetBranch(string branchName) { - if (tree.ContainsKey(branchName) && tree[branchName] != null) + if (Tree != null && (Tree.ContainsKey(branchName) && Tree[branchName] != null)) { - return tree[branchName]; + return Tree[branchName]; } - Dictionary tmp = Store.read(branchName); - if (tmp != null) - { - tree[branchName] = tmp; - return tmp; - } - return null; + Dictionary tmp = _store.Read(branchName); + if (tmp == null) return null; + + Tree[branchName] = tmp; + return tmp; } @@ -547,16 +532,16 @@ private string _helperMD5Hash(string input) - private HDStore Store = null; + private HdStore _store = null; public bool UseProxy { get { - return config["use_proxy"]; + return Config["use_proxy"]; } set { - config["use_proxy"] = value; + Config["use_proxy"] = value; } } @@ -565,11 +550,11 @@ public bool Cacherequests { get { - return Convert.ToBoolean(config["cache_requests"]); + return Convert.ToBoolean(Config["cache_requests"]); } set { - config["cache_requests"] = value.ToString(); + Config["cache_requests"] = value.ToString(); } } @@ -577,11 +562,11 @@ public bool Debug { get { - return Convert.ToBoolean(config["debug"]); + return Convert.ToBoolean(Config["debug"]); } set { - config["debug"] = value.ToString(); + Config["debug"] = value.ToString(); } } @@ -589,22 +574,22 @@ public string Username { get { - return config["username"]; + return Config["username"]; } set { - config["username"] = value; + Config["username"] = value; } } public string Secret { get { - return config["secret"]; + return Config["secret"]; } set { - config["secret"] = value; + Config["secret"] = value; } } @@ -612,11 +597,11 @@ public string ProxyServer { get { - return config["proxy_server"]; + return Config["proxy_server"]; } set { - config["proxy_server"] = value; + Config["proxy_server"] = value; } } @@ -624,22 +609,22 @@ public int ProxyPort { get { - return config["proxy_port"]; + return Config["proxy_port"]; } set { - config["proxy_port"] = value; + Config["proxy_port"] = value; } } public string ProxyUser { get { - return config["proxy_user"]; + return Config["proxy_user"]; } set { - config["proxy_user"] = value; + Config["proxy_user"] = value; } } @@ -647,17 +632,17 @@ public string ProxyPass { get { - return config["proxy_pass"]; + return Config["proxy_pass"]; } set { - config["proxy_pass"] = value; + Config["proxy_pass"] = value; } } - public Dictionary detectRequest = new Dictionary(); + public Dictionary DetectRequest = new Dictionary(); - public void setDetectVar(string key, string value) { detectRequest[key.ToLower()] = value; } + public void SetDetectVar(string key, string value) { DetectRequest[key.ToLower()] = value; } @@ -668,27 +653,26 @@ public int ReadTimeout { get { - return config["timeout"]; + return Config["timeout"]; } set { - config["timeout"] = value; + Config["timeout"] = value; } } - private Stream responseStream = null; - protected static BinaryReader reader { get; set; } - public bool isDownloadableFiles = false; - - public List deviceUAFilterList; - public List extraUAFilterList; - protected static string rawreply; - protected string log; - protected Dictionary rawReply = null; - protected Dictionary tree = new Dictionary(); - public int maxJsonLength = 40000000; + private Stream _responseStream = null; + protected static BinaryReader Reader { get; set; } + public bool IsDownloadableFiles = false; + public List DeviceUaFilterList; + public List ExtraUaFilterList; + protected static string Rawreply; + protected string Log; + protected Dictionary RawReply = null; + protected Dictionary Tree = new Dictionary(); + - protected string error = ""; + protected string Error = ""; @@ -713,14 +697,14 @@ public string ApplicationRootDirectory /// /// Return replay /// - protected void setRawReply() + protected void SetRawReply() { - var jss = new JavaScriptSerializer(); - jss.MaxJsonLength = maxJsonLength; - rawreply = jss.Serialize(reply); + JavaScriptSerializer jss = new JavaScriptSerializer(); + jss.MaxJsonLength = MaxJsonLength; + Rawreply = jss.Serialize(Reply); } - public string getRawReply() { return rawreply; } + public string GetRawReply() { return Rawreply; } public string ApiServer { get; set; } diff --git a/HandsetDetectionAPI/HDCache.cs b/HandsetDetectionAPI/HDCache.cs index ce794b8c..0d35d1b5 100644 --- a/HandsetDetectionAPI/HDCache.cs +++ b/HandsetDetectionAPI/HDCache.cs @@ -10,30 +10,31 @@ namespace HandsetDetectionAPI { - public class HDCache + public class HdCache { - private int maxJsonLength = 40000000; - string prefix = "hd4-"; + private static int _maxJsonLength = 40000000; + string _prefix = "hd4-"; //int duration = 7200; - ObjectCache myCache; - CacheItemPolicy policy = new CacheItemPolicy(); + ObjectCache _myCache; + CacheItemPolicy _policy = new CacheItemPolicy(); + JavaScriptSerializer _jss = new JavaScriptSerializer { MaxJsonLength = _maxJsonLength }; - public HDCache() + public HdCache() { - policy.AbsoluteExpiration = new DateTimeOffset(DateTime.Now.AddHours(24)); - NameValueCollection CacheSettings = new NameValueCollection(3); - CacheSettings.Add("CacheMemoryLimitMegabytes", Convert.ToString(200)); - this.myCache = MemoryCache.Default; + _policy.AbsoluteExpiration = new DateTimeOffset(DateTime.Now.AddHours(24)); + NameValueCollection cacheSettings = new NameValueCollection(3) + { + {"CacheMemoryLimitMegabytes", Convert.ToString(200)} + }; + _myCache = MemoryCache.Default; } - public Dictionary write(string key, dynamic value) + public Dictionary Write(string key, dynamic value) { if (value != null && key != "") { - var jss = new JavaScriptSerializer(); - jss.MaxJsonLength = this.maxJsonLength; - string storethis = jss.Serialize(value); - this.myCache.Set(this.prefix + key, storethis, policy); + string storethis = _jss.Serialize(value); + _myCache.Set(_prefix + key, storethis, _policy); return value; } else @@ -42,30 +43,28 @@ public Dictionary write(string key, dynamic value) } } - public Dictionary read(string key) + public Dictionary Read(string key) { try { - string fromCache = this.myCache.Get(this.prefix + key) as string; - var jss = new JavaScriptSerializer(); - jss.MaxJsonLength = this.maxJsonLength; - return jss.Deserialize>(fromCache); + string fromCache = _myCache.Get(_prefix + key) as string; + if (fromCache != null) return _jss.Deserialize>(fromCache); } catch (Exception) { // Not in cache - - return null; + } + return null; } - public bool purge() + public bool Purge() { try { - foreach (var item in this.myCache.Select(kvp => kvp.Key)) + foreach (string item in _myCache.Select(kvp => kvp.Key)) { - this.myCache.Remove(item); + _myCache.Remove(item); } return true; } diff --git a/HandsetDetectionAPI/HDDevice.cs b/HandsetDetectionAPI/HDDevice.cs index 3710127d..6c86daf8 100644 --- a/HandsetDetectionAPI/HDDevice.cs +++ b/HandsetDetectionAPI/HDDevice.cs @@ -9,41 +9,41 @@ namespace HandsetDetectionAPI { - public class HDDevice : HDBase + public class HdDevice : HdBase { - string DETECTIONV4_STANDARD = "0"; - string DETECTIONV4_GENERIC = "1"; + string _detectionv4Standard = "0"; + string _detectionv4Generic = "1"; - private HDStore Store; - private HDExtra Extra; + private HdStore _store; + private HdExtra _extra; - public HDDevice() + public HdDevice() { - this.Store = HDStore.Instance; - this.Extra = new HDExtra(); + _store = HdStore.Instance; + _extra = new HdExtra(); } /// /// Find all device vendors /// /// bool true on success, false otherwise. Use getReply to inspect results on success. - public bool localDeviceVendors() + public bool LocalDeviceVendors() { - reply = new Dictionary(); - Dictionary data = fetchDevices(); + Reply = new Dictionary(); + Dictionary data = FetchDevices(); if (data == null) return false; - var temp = new HashSet(); - foreach (var item in data["devices"]) + HashSet temp = new HashSet(); + foreach (dynamic item in data["devices"]) { temp.Add(item["Device"]["hd_specs"]["general_vendor"].ToString()); } - reply["vendor"] = temp.OrderBy(c => c).ToList(); - reply["message"] = "OK"; - reply["status"] = 0; - setRawReply(); - return setError(0, "OK"); + Reply["vendor"] = temp.OrderBy(c => c).ToList(); + Reply["message"] = "OK"; + Reply["status"] = 0; + SetRawReply(); + return SetError(0, "OK"); } /// @@ -51,10 +51,10 @@ public bool localDeviceVendors() /// /// vendor The device vendor /// true on success, false otherwise. Use getRawReply to inspect results on success - public bool localDeviceModels(string vendor) + public bool LocalDeviceModels(string vendor) { - reply = new Dictionary(); - Dictionary data = fetchDevices(); + Reply = new Dictionary(); + Dictionary data = FetchDevices(); if (data == null) return false; @@ -68,23 +68,23 @@ public bool localDeviceModels(string vendor) temp.Add(item["Device"]["hd_specs"]["general_model"].ToString()); } string key = vendor + " "; - if (item["Device"]["hd_specs"]["general_aliases"].ToString() != "") + + if (item["Device"]["hd_specs"]["general_aliases"].ToString() == "") continue; + + foreach (string aliasItem in item["Device"]["hd_specs"]["general_aliases"]) { - foreach (string alias_item in item["Device"]["hd_specs"]["general_aliases"]) + int result = aliasItem.IndexOf(key, StringComparison.Ordinal); + if (result == 0) { - int result = alias_item.IndexOf(key); - if (result == 0) - { - temp.Add(alias_item.Replace(key, "")); - } + temp.Add(aliasItem.Replace(key, "")); } } } - reply["model"] = temp.OrderBy(c => c).ToList(); - reply["status"] = 0; - reply["message"] = "OK"; - this.setRawReply(); - return this.setError(0, "OK"); + Reply["model"] = temp.OrderBy(c => c).ToList(); + Reply["status"] = 0; + Reply["message"] = "OK"; + SetRawReply(); + return SetError(0, "OK"); } /// @@ -93,30 +93,30 @@ public bool localDeviceModels(string vendor) /// vendor The device vendor /// model The device model /// true on success, false otherwise. Use getRawReply to inspect results on success - public bool localDeviceView(string vendor, string model) + public bool LocalDeviceView(string vendor, string model) { - Dictionary data = fetchDevices(); + Dictionary data = FetchDevices(); if (data == null) return false; vendor = vendor.ToLower(); model = model.ToLower(); foreach (Dictionary item in data["devices"]) { - if (vendor == (item["Device"]["hd_specs"]["general_vendor"].ToString().ToLower()) && model == item["Device"]["hd_specs"]["general_model"].ToString().ToLower()) + if (string.Compare(vendor, (item["Device"]["hd_specs"]["general_vendor"].ToString().ToLower()), StringComparison.OrdinalIgnoreCase) == 0 && string.Compare(model, item["Device"]["hd_specs"]["general_model"].ToString(), StringComparison.OrdinalIgnoreCase) == 0) { - reply = new Dictionary(); - reply["device"] = item["Device"]["hd_specs"]; - reply["status"] = 0; - reply["message"] = "OK"; - this.setRawReply(); - return this.setError(0, "OK"); + Reply = new Dictionary(); + Reply["device"] = item["Device"]["hd_specs"]; + Reply["status"] = 0; + Reply["message"] = "OK"; + SetRawReply(); + return SetError(0, "OK"); } } - reply = new Dictionary(); - reply["status"] = 301; - reply["message"] = "Nothing found"; - this.setRawReply(); - return this.setError(301, "Nothing found"); + Reply = new Dictionary(); + Reply["status"] = 301; + Reply["message"] = "Nothing found"; + SetRawReply(); + return SetError(301, "Nothing found"); } /// @@ -125,25 +125,25 @@ public bool localDeviceView(string vendor, string model) /// key /// value /// true on success, false otherwise. Use getRawReply to inspect results on success - public bool localWhatHas(string key, string value) + public bool LocalWhatHas(string key, string value) { - Dictionary data = this.fetchDevices(); + Dictionary data = FetchDevices(); if (data == null) return false; value = value.ToLower(); key = key.ToLower(); string s = ""; Type sType = s.GetType(); - var temp = new ArrayList(); + ArrayList temp = new ArrayList(); foreach (Dictionary item in data["devices"]) { if (item["Device"]["hd_specs"][key].ToString() == "") continue; - var match = false; + bool match = false; if (item["Device"]["hd_specs"][key].GetType() == sType) { string check = item["Device"]["hd_specs"][key].ToString().ToLower(); - if (check.IndexOf(value) >= 0) + if (check.IndexOf(value, StringComparison.Ordinal) >= 0) match = true; } else @@ -151,25 +151,25 @@ public bool localWhatHas(string key, string value) foreach (string check in item["Device"]["hd_specs"][key]) { string tmpcheck = check.ToLower(); - if (tmpcheck.IndexOf(value) >= 0) + if (tmpcheck.IndexOf(value, StringComparison.Ordinal) >= 0) match = true; } } - if (match == true) + if (match != true) continue; + Dictionary sublist = new Dictionary { - Dictionary sublist = new Dictionary(); - sublist.Add("id", item["Device"]["_id"].ToString()); - sublist.Add("general_vendor", item["Device"]["hd_specs"]["general_vendor"].ToString()); - sublist.Add("general_model", item["Device"]["hd_specs"]["general_model"].ToString()); - temp.Add(sublist); - } - } - reply = new Dictionary(); - reply["devices"] = temp; - reply["status"] = 0; - reply["message"] = "OK"; - this.setRawReply(); - return this.setError(0, "OK"); + {"id", item["Device"]["_id"].ToString()}, + {"general_vendor", item["Device"]["hd_specs"]["general_vendor"].ToString()}, + {"general_model", item["Device"]["hd_specs"]["general_model"].ToString()} + }; + temp.Add(sublist); + } + Reply = new Dictionary(); + Reply["devices"] = temp; + Reply["status"] = 0; + Reply["message"] = "OK"; + SetRawReply(); + return SetError(0, "OK"); } /// @@ -177,7 +177,7 @@ public bool localWhatHas(string key, string value) /// /// headers HTTP headers as an assoc array. keys are standard http header names eg user-agent, x-wap-profile /// true on success, false otherwise - public bool localDetect(Dictionary headers) + public bool LocalDetect(Dictionary headers) { string hardwareInfo = string.Empty; @@ -187,12 +187,12 @@ public bool localDetect(Dictionary headers) headers.Remove("x-local-hardwareinfo"); } - if (!(this.hasBiKeys(headers) is Boolean)) + if (!(HasBiKeys(headers) is bool)) { - return v4MatchBuildInfo(headers); + return V4MatchBuildInfo(headers); } - return v4MatchHttpHeaders(headers, hardwareInfo); + return V4MatchHttpHeaders(headers, hardwareInfo); } /// @@ -201,18 +201,18 @@ public bool localDetect(Dictionary headers) /// deviceId : The ID of the device to check. /// Properties extracted from the device (display_x, display_y etc .. ) /// - public Dictionary findRating(string deviceId, Dictionary props) + public Dictionary FindRating(string deviceId, Dictionary props) { - var device = findById(deviceId); + Dictionary device = FindById(deviceId); if (device["Device"]["hd_specs"] is string) return null; - var specs = device["Device"]["hd_specs"]; + dynamic specs = device["Device"]["hd_specs"]; - Double total = 0; - var result = new Dictionary(); - var adjX = 0; - var adjY = 0; + double total = 0; + Dictionary result = new Dictionary(); + int adjX = 0; + int adjY = 0; // Display Resolution - Worth 40 points if correct if (props["display_x"].ToString() != "" && props["display_y"].ToString() != "") { @@ -252,8 +252,6 @@ public Dictionary findRating(string deviceId, Dictionary findRating(string deviceId, Dictionary Convert.ToInt32(c)); + int valuesSum = result.Values.Sum(c => Convert.ToInt32(c)); result["score"] = (total == 0) ? (int)0 : (int)Math.Round(Convert.ToDouble(valuesSum / total) * 100, 2); result["possible"] = total; @@ -319,7 +317,7 @@ public Dictionary findRating(string deviceId, Dictionarystring specsField : Either "platform', 'browser', 'language' /// /// - public void specsOverlay(string specsField, ref dynamic device, Dictionary specs) + public void SpecsOverlay(string specsField, ref dynamic device, Dictionary specs) { switch (specsField) { @@ -373,13 +371,13 @@ public void specsOverlay(string specsField, ref dynamic device, Dictionary /// hardwareInfo String of light weight device property information, separated by ':' /// partial specs array of information we can use to improve detection accuracy - private Dictionary infoStringToArray(string hardwareInfo) + private Dictionary InfoStringToArray(string hardwareInfo) { Dictionary result = new Dictionary(); // Remove the header or cookie name from the string 'x-specs1a=' - if (hardwareInfo.IndexOf("=") >= 0) + if (hardwareInfo.IndexOf("=", StringComparison.Ordinal) >= 0) { - List lstHardwareInfo = hardwareInfo.Split(new String[] { "=" }, StringSplitOptions.RemoveEmptyEntries).ToList(); + List lstHardwareInfo = hardwareInfo.Split(new string[] { "=" }, StringSplitOptions.RemoveEmptyEntries).ToList(); if (lstHardwareInfo.Count > 1) { hardwareInfo = lstHardwareInfo[1]; @@ -389,17 +387,17 @@ private Dictionary infoStringToArray(string hardwareInfo) return result; } } - reply = new Dictionary(); - var info = hardwareInfo.Split(new String[] { ":" }, StringSplitOptions.RemoveEmptyEntries).ToList(); + Reply = new Dictionary(); + List info = hardwareInfo.Split(new string[] { ":" }, StringSplitOptions.RemoveEmptyEntries).ToList(); if (info.Count != 4) { return result; } - reply["display_x"] = Convert.ToInt32(info[0].Trim()); - reply["display_y"] = Convert.ToInt32(info[1].Trim()); - reply["display_pixel_ratio"] = Convert.ToInt32(info[2].Trim()); - reply["benchmark"] = Convert.ToInt32(info[3].Trim()); - return reply; + Reply["display_x"] = Convert.ToInt32(info[0].Trim()); + Reply["display_y"] = Convert.ToInt32(info[1].Trim()); + Reply["display_pixel_ratio"] = Convert.ToInt32(info[2].Trim()); + Reply["benchmark"] = Convert.ToInt32(info[3].Trim()); + return Reply; } /// @@ -407,14 +405,11 @@ private Dictionary infoStringToArray(string hardwareInfo) /// /// /// - private void hardwareInfoOverlay(ref dynamic device, Dictionary infoArray) + private void HardwareInfoOverlay(ref dynamic device, Dictionary infoArray) { - device["Device"]["hd_ops"]["display_x"] = infoArray["display_x"]; device["Device"]["hd_ops"]["display_y"] = infoArray["display_y"]; device["Device"]["hd_ops"]["display_pixel_ratio"] = infoArray["display_pixel_ratio"]; - - } /// @@ -429,28 +424,26 @@ private void hardwareInfoOverlay(ref dynamic device, Dictionary /// /// /// array The matched device or null if not found - private dynamic matchDevice(Dictionary headers) + private dynamic MatchDevice(Dictionary headers) { - string agent = ""; // Opera mini sometimes puts the vendor # model in the header - nice! ... sometimes it puts ? # ? in as well if (headers.ContainsKey("x-operamini-phone") && headers["x-operamini-phone"].trim() != "? # ?") { - var id = this.getMatch("x-operamini-phone", headers["x-operamini-phone"], DETECTIONV4_STANDARD, "x-operamini-phone", "device"); - if (!(id is Boolean)) + dynamic id = this.GetMatch("x-operamini-phone", headers["x-operamini-phone"], _detectionv4Standard, "x-operamini-phone", "device"); + if (!(id is bool)) { - return this.findById(id); + return this.FindById(id); } - agent = headers["x-operamini-phone"]; headers.Remove("x-operamini-phone"); } // Profile header matching if (headers.ContainsKey("profile")) { - var id = this.getMatch("profile", headers["profile"], DETECTIONV4_STANDARD, "profile", "device"); - if (!(id is Boolean)) + dynamic id = this.GetMatch("profile", headers["profile"], _detectionv4Standard, "profile", "device"); + if (!(id is bool)) { - return this.findById(id); + return this.FindById(id); } headers.Remove("profile"); } @@ -458,56 +451,46 @@ private dynamic matchDevice(Dictionary headers) // Profile header matching if (headers.ContainsKey("x-wap-profile")) { - var id = this.getMatch("x-wap-profile", headers["x-wap-profile"], DETECTIONV4_STANDARD, "x-wap-profile", "device"); - if (!(id is Boolean)) + dynamic id = this.GetMatch("x-wap-profile", headers["x-wap-profile"], _detectionv4Standard, "x-wap-profile", "device"); + if (!(id is bool)) { - return this.findById(id); + return this.FindById(id); } headers.Remove("x-wap-profile"); } - List order = this.detectionConfig["device-ua-order"]; - foreach (var item in headers) + List order = DetectionConfig["device-ua-order"]; + foreach (KeyValuePair item in headers.Where(item => !order.Contains(item.Key) && Regex.IsMatch(item.Key, "^x-"))) { - if (!order.Contains(item.Key) && Regex.IsMatch(item.Key, "^x-")) - { - order.Add(item.Key); - } + order.Add(item.Key); } - foreach (var item in order) + foreach (dynamic id in from item in order where headers.ContainsKey(item) select this.GetMatch("user-agent", headers[item], _detectionv4Standard, item, "device") into id where !(id is bool) select id) { - if (headers.ContainsKey(item)) - { - var id = this.getMatch("user-agent", headers[item], DETECTIONV4_STANDARD, item, "device"); - if (!(id is Boolean)) - { - return this.findById(id); - } - } + return this.FindById(id); } - bool HasGetData = false; + bool hasGetData = false; dynamic itemid = ""; // Generic matching - Match of last resort if (headers.ContainsKey("x-operamini-phone-ua")) { - itemid = this.getMatch("x-operamini-phone-ua", headers["x-operamini-phone-ua"], DETECTIONV4_GENERIC, "x-operamini-phone-ua", "device"); + itemid = this.GetMatch("x-operamini-phone-ua", headers["x-operamini-phone-ua"], _detectionv4Generic, "x-operamini-phone-ua", "device"); } - if (!HasGetData && headers.ContainsKey("agent")) + if (!hasGetData && headers.ContainsKey("agent")) { - itemid = this.getMatch("agent", headers["agent"], DETECTIONV4_GENERIC, "agent", "device"); + itemid = this.GetMatch("agent", headers["agent"], _detectionv4Generic, "agent", "device"); } - if (!HasGetData && headers.ContainsKey("user-agent")) + if (!hasGetData && headers.ContainsKey("user-agent")) { - itemid = this.getMatch("user-agent", headers["user-agent"], DETECTIONV4_GENERIC, "user-agent", "device"); + itemid = this.GetMatch("user-agent", headers["user-agent"], _detectionv4Generic, "user-agent", "device"); if (itemid is string) - HasGetData = true; + hasGetData = true; } - if (HasGetData) + if (hasGetData) { - return this.findById(itemid); + return this.FindById(itemid); } return false; @@ -518,30 +501,30 @@ private dynamic matchDevice(Dictionary headers) /// /// id /// list of device on success, false otherwise - public Dictionary findById(string id) + public Dictionary FindById(string id) { - return this.Store.read(string.Format("Device_{0}", id)); + return _store.Read(string.Format("Device_{0}", id)); } /// /// Internal helper for building a list of all devices. /// /// Dictionary List of all devices. - private Dictionary fetchDevices() + private Dictionary FetchDevices() { try { - Dictionary data = this.Store.fetchDevices(); - if (!(data.Count() > 0)) + Dictionary data = _store.FetchDevices(); + if (!(data.Any())) { - this.setError(299, "Error : fetchDevices cannot read files from store."); + SetError(299, "Error : fetchDevices cannot read files from store."); } return data; } catch (Exception ex) { - this.setError(299, "Exception : " + ex.Message + " " + ex.StackTrace); + SetError(299, "Exception : " + ex.Message + " " + ex.StackTrace); } return null; } @@ -552,32 +535,32 @@ private Dictionary fetchDevices() /// /// Buildinfo key/value array /// mixed device array on success, false otherwise - public dynamic v4MatchBuildInfo(Dictionary buildInfo) + public dynamic V4MatchBuildInfo(Dictionary buildInfo) { - dynamic device = null; - dynamic platform = null; - this.detectedRuleKey = null; - reply = new Dictionary(); + // Nothing to check if (buildInfo.Count == 0) return false; + + DetectedRuleKey = null; + Reply = new Dictionary(); //this.buildInfo = buildInfo; // Device Detection - device = this.v4MatchBIHelper(buildInfo, "device"); + dynamic device = V4MatchBiHelper(buildInfo); if (device == null || device.Count == 0) return false; // Platform Detection - platform = v4MatchBIHelper(buildInfo, "platform"); - if (platform != null && !(platform.Count == 0)) - this.specsOverlay("platform", ref device, platform["Extra"]); + dynamic platform = V4MatchBiHelper(buildInfo, "platform"); + if (platform != null && platform.Count != 0) + this.SpecsOverlay("platform", ref device, platform["Extra"]); - reply["hd_specs"] = device["Device"]["hd_specs"]; - return this.setError(0, "OK"); + Reply["hd_specs"] = device["Device"]["hd_specs"]; + return SetError(0, "OK"); } /// @@ -586,28 +569,29 @@ public dynamic v4MatchBuildInfo(Dictionary buildInfo) /// A buildInfo key/value array /// /// - private Dictionary v4MatchBIHelper(Dictionary buildInfo, string category = "device") + private Dictionary V4MatchBiHelper(Dictionary buildInfo, string category = "device") { // ***** Device Detection ***** - var confBIKeys = new Dictionary(); - if (detectionConfig.ContainsKey(string.Format("{0}-bi-order", category))) + Dictionary confBiKeys = new Dictionary(); + if (DetectionConfig.ContainsKey(string.Format("{0}-bi-order", category))) { - confBIKeys = detectionConfig[string.Format("{0}-bi-order", category)]; + confBiKeys = DetectionConfig[string.Format("{0}-bi-order", category)]; } - if (confBIKeys.Count == 0 || buildInfo.Count == 0) + if (confBiKeys.Count == 0 || buildInfo.Count == 0) return null; - var hints = new Dictionary(); - foreach (KeyValuePair platform in confBIKeys) + foreach (KeyValuePair platform in confBiKeys) { - var value = ""; + string value = ""; List> platformValue = platform.Value; - foreach (List tuple in platformValue) + for (int index = 0; index < platformValue.Count; index++) { + List tuple = platformValue[index]; bool checking = true; - foreach (var item in tuple) + for (int i = 0; i < tuple.Count; i++) { + string item = tuple[i]; if (!buildInfo.ContainsKey(item)) { checking = false; @@ -619,37 +603,25 @@ private Dictionary v4MatchBIHelper(Dictionary } } - if (checking) + if (!checking) continue; + + value = value.Trim(("| \t\n\r\0\x0B").ToArray()); + string subtree = string.Compare(category, "device", StringComparison.OrdinalIgnoreCase) == 0 ? _detectionv4Standard : category; + dynamic id = GetMatch("buildinfo", value, subtree, "buildinfo", category); + if (!(id is bool)) { - value = value.Trim(("| \t\n\r\0\x0B").ToArray()); - hints[value] = value; - var subtree = (category == "device") ? DETECTIONV4_STANDARD : category; - var _id = this.getMatch("buildinfo", value, subtree, "buildinfo", category); - if (!(_id is Boolean)) - { - return (category == "device") ? this.findById(_id) : this.Extra.findById(_id); - } + return string.Compare(category, "device", StringComparison.OrdinalIgnoreCase) == 0 ? this.FindById(id) : _extra.FindById(id); } } } // If we get this far then not found, so try generic. - var objplatform = this.hasBiKeys(buildInfo); - if (!(objplatform is Boolean)) - { - var objTry = new string[2] { string.Format("generic|{0}", objplatform.Key.ToLower()), string.Format("{0}|generic", objplatform.Key.ToLower()) }; + dynamic objplatform = HasBiKeys(buildInfo); + if (objplatform is bool) return null; - foreach (var objvalue in objTry) - { - var subtree = (category == "device") ? DETECTIONV4_GENERIC : category; - var _id = this.getMatch("buildinfo", objvalue, subtree, "buildinfo", category); - if (!(_id is Boolean)) - { - return (category == "device") ? this.findById(_id) : this.Extra.findById(_id); - } - } - } - return null; + string[] objTry = new string[2] { string.Format("generic|{0}", objplatform.Key.ToLower()), string.Format("{0}|generic", objplatform.Key.ToLower()) }; + + return (from objvalue in objTry let subtree = string.Compare(category, "device", StringComparison.OrdinalIgnoreCase) == 0 ? _detectionv4Generic : category select GetMatch("buildinfo", objvalue, subtree, "buildinfo", category) into id where !(id is bool) select string.Compare(category, "device", StringComparison.OrdinalIgnoreCase) == 0 ? this.FindById(id) : _extra.FindById(id)).FirstOrDefault(); } /// @@ -661,17 +633,8 @@ private Dictionary v4MatchBIHelper(Dictionary /// headers Set of sanitized http headers /// hardwareInfo Information about the hardware /// - private dynamic v4MatchHttpHeaders(Dictionary headers, string hardwareInfo) + private dynamic V4MatchHttpHeaders(Dictionary headers, string hardwareInfo) { - dynamic device = new Dictionary(); - dynamic platform = new Dictionary(); - dynamic browser = new Dictionary(); - dynamic app = new Dictionary(); - dynamic ratingResult = new Dictionary(); - this.detectedRuleKey = new Dictionary(); ; - reply = new Dictionary(); - dynamic hwProps = ""; - if (headers == null || headers.Count == 0) { return false; @@ -687,29 +650,27 @@ private dynamic v4MatchHttpHeaders(Dictionary headers, string h headers.Remove("host"); } + DetectedRuleKey = new Dictionary(); + Reply = new Dictionary(); + dynamic hwProps = ""; Dictionary deviceHeaders = new Dictionary(); Dictionary extraHeaders = new Dictionary(); // Sanitize headers & cleanup language - foreach (var item in headers) + foreach (KeyValuePair item in headers) { string key = item.Key.ToLower(); string value = item.Value; - if (item.Key.ToLower() == "accept-language" || item.Key.ToLower() == "content-language") + if (string.Compare(item.Key, "accept-language", StringComparison.OrdinalIgnoreCase) == 0 || string.Compare(item.Key, "content-language", StringComparison.OrdinalIgnoreCase) == 0) { key = "language"; - var tmp = Regex.Split(Convert.ToString(item.Value).Replace(" ", ""), "[,;]"); + dynamic tmp = Regex.Split(Convert.ToString(item.Value).Replace(" ", ""), "[,;]"); if (tmp.Length == 0) { continue; } - else - { - value = cleanStr(tmp[0]); - } - - + value = CleanStr(tmp[0]); } if (deviceHeaders.ContainsKey(key)) @@ -724,67 +685,67 @@ private dynamic v4MatchHttpHeaders(Dictionary headers, string h if (extraHeaders.ContainsKey(key)) { - extraHeaders[key] = Extra.extraCleanStr(value); + extraHeaders[key] = _extra.ExtraCleanStr(value); } else { - extraHeaders.Add(key, Extra.extraCleanStr(value)); + extraHeaders.Add(key, _extra.ExtraCleanStr(value)); } } - device = matchDevice(deviceHeaders); + dynamic device = MatchDevice(deviceHeaders); - if (device is Boolean) + if (device is bool) { - return setError(301, "Not Found"); + return SetError(301, "Not Found"); } if (!string.IsNullOrEmpty(hardwareInfo)) { - hwProps = infoStringToArray(hardwareInfo); + hwProps = InfoStringToArray(hardwareInfo); } // Stop on detect set - Tidy up and return - if (!(device["Device"]["hd_ops"]["stop_on_detect"].ToString() == "") && device["Device"]["hd_ops"]["stop_on_detect"].ToString() == "1") + if (device["Device"]["hd_ops"]["stop_on_detect"].ToString() != "" && device["Device"]["hd_ops"]["stop_on_detect"].ToString() == "1") { // Check for hardwareInfo overlay if (!string.IsNullOrEmpty(device["Device"]["hd_ops"]["overlay_result_specs"])) { if (hwProps is IDictionary) { - hardwareInfoOverlay(ref device, (Dictionary)hwProps); + HardwareInfoOverlay(ref device, (Dictionary)hwProps); } } - reply["hd_specs"] = device["Device"]["hd_specs"]; - return setError(0, "OK"); + Reply["hd_specs"] = device["Device"]["hd_specs"]; + return SetError(0, "OK"); } // Get extra info - platform = Extra.matchExtra("platform", extraHeaders); - browser = Extra.matchExtra("browser", extraHeaders); - app = Extra.matchExtra("app", extraHeaders); - var language = Extra.matchLanguage(extraHeaders); + dynamic platform = _extra.MatchExtra("platform", extraHeaders); + dynamic browser = _extra.MatchExtra("browser", extraHeaders); + dynamic app = _extra.MatchExtra("app", extraHeaders); + dynamic language = _extra.MatchLanguage(extraHeaders); // Find out if there is any contention on the detected rule. - var deviceList = this.getHighAccuracyCandidates(); + dynamic deviceList = GetHighAccuracyCandidates(); - if (!(deviceList is Boolean)) + if (!(deviceList is bool)) { - var pass1List = new List(); + List pass1List = new List(); // Resolve contention with OS check - if (!(platform is Boolean)) + if (!(platform is bool)) { - Extra.set(platform); + _extra.Set(platform); - foreach (var item in deviceList) + foreach (dynamic item in deviceList) { - var tryDevice = this.findById(item); - var modelno = tryDevice["Device"]["hd_specs"]["general_model"]; - if (Extra.verifyPlatform(tryDevice["Device"]["hd_specs"])) + dynamic tryDevice = this.FindById(item); + + if (_extra.VerifyPlatform(tryDevice["Device"]["hd_specs"])) { pass1List.Add(item); } @@ -796,55 +757,52 @@ private dynamic v4MatchHttpHeaders(Dictionary headers, string h { // Score the list based on hardware List result = new List(); - foreach (var id in pass1List) + for (int index = 0; index < pass1List.Count; index++) { - var tmp = findRating(id, hwProps); - if (tmp.Count > 0) - { - tmp["_id"] = id; - result.Add(tmp); - } + string id = pass1List[index]; + dynamic tmp = FindRating(id, hwProps); + + if (tmp.Count <= 0) continue; + + tmp["_id"] = id; + result.Add(tmp); } // Sort the results //usort($result, array($this, 'hd_sortByScore')); - ratingResult = result; - var bestRatedDevice = GetDeviceFromRatingResult(result); - var objDevice = this.findById(bestRatedDevice["_id"]); + Dictionary bestRatedDevice = GetDeviceFromRatingResult(result); + dynamic objDevice = this.FindById(bestRatedDevice["_id"]); if (objDevice.Count > 0) { - var modelno1 = objDevice["Device"]["hd_specs"]["general_model"]; - device = objDevice; } - } } // Overlay specs - if (!(platform is Boolean)) + if (!(platform is bool)) { - specsOverlay("platform", ref device, platform["Extra"]); + SpecsOverlay("platform", ref device, platform["Extra"]); } - if (!(browser is Boolean)) + if (!(browser is bool)) { - specsOverlay("browser", ref device, browser["Extra"]); + SpecsOverlay("browser", ref device, browser["Extra"]); } - if (!(app is Boolean)) + if (!(app is bool)) { - specsOverlay("app", ref device, app["Extra"]); + SpecsOverlay("app", ref device, app["Extra"]); } - if (!(language is Boolean)) + if (!(language is bool)) { - specsOverlay("language", ref device, language["Extra"]); + SpecsOverlay("language", ref device, language["Extra"]); } // Overlay hardware info result if required if (device["Device"]["hd_ops"]["overlay_result_specs"].ToString() == "1" && !string.IsNullOrEmpty(hardwareInfo)) - hardwareInfoOverlay(ref device, hwProps); + HardwareInfoOverlay(ref device, hwProps); - reply["hd_specs"] = device["Device"]["hd_specs"]; - return setError(0, "OK");//for meantime + Reply["hd_specs"] = device["Device"]["hd_specs"]; + return SetError(0, "OK");//for meantime } /// @@ -852,10 +810,10 @@ private dynamic v4MatchHttpHeaders(Dictionary headers, string h /// /// /// a list of candidate devices which have this detection rule or false otherwise. - private dynamic getHighAccuracyCandidates() + private dynamic GetHighAccuracyCandidates() { - var branch = this.getBranch("hachecks"); - var ruleKey = detectedRuleKey["device"]; + Dictionary branch = GetBranch("hachecks"); + dynamic ruleKey = DetectedRuleKey["device"]; if (branch.ContainsKey(ruleKey)) { return branch[ruleKey]; @@ -868,7 +826,7 @@ private dynamic getHighAccuracyCandidates() /// /// $headers HTTP Headers /// true if required, false otherwise - public bool isHelperUseful(Dictionary headers) + public bool IsHelperUseful(Dictionary headers) { if (headers.Count == 0) return false; @@ -876,13 +834,10 @@ public bool isHelperUseful(Dictionary headers) headers.Remove("ip"); headers.Remove("host"); - if (!localDetect(headers)) - return false; - - if (getHighAccuracyCandidates() is Boolean) + if (!LocalDetect(headers)) return false; - return true; + return !(GetHighAccuracyCandidates() is bool); } /// @@ -910,28 +865,25 @@ public Dictionary GetDeviceFromRatingResult(List devic { Dictionary bestDevice = null; - foreach (Dictionary item in deviceResult) + for (int index = 0; index < deviceResult.Count; index++) { + Dictionary item = deviceResult[index]; if (bestDevice == null) { bestDevice = item; continue; } - else + + if (item["score"] > bestDevice["score"]) + { + bestDevice = item; + } + else if (item["score"] == bestDevice["score"]) { - if (item["score"] > bestDevice["score"]) + if (item["distance"] < bestDevice["distance"]) { bestDevice = item; } - else if (item["score"] == bestDevice["score"]) - { - if (item["distance"] < bestDevice["distance"]) - { - bestDevice = item; - } - - } - } } diff --git a/HandsetDetectionAPI/HDExtra.cs b/HandsetDetectionAPI/HDExtra.cs index f2c7f0b7..479c0dff 100644 --- a/HandsetDetectionAPI/HDExtra.cs +++ b/HandsetDetectionAPI/HDExtra.cs @@ -1,25 +1,23 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Text.RegularExpressions; -using System.Threading.Tasks; namespace HandsetDetectionAPI { - public class HDExtra : HDBase + public class HdExtra : HdBase { - private HDStore Store = null; - Dictionary data = null; - public HDExtra() + private HdStore _store = null; + Dictionary _data = null; + public HdExtra() : base() { - this.Store = HDStore.Instance; + this._store = HdStore.Instance; } - public void set(Dictionary data) + public void Set(Dictionary data) { - this.data = data; + this._data = data; } /// @@ -28,38 +26,29 @@ public void set(Dictionary data) /// className Is 'platform','browser' or 'app' /// /// an Extra on success, false otherwise - public dynamic matchExtra(string className, Dictionary headers) + public dynamic MatchExtra(string className, Dictionary headers) { headers.Remove("profile"); - List orders = detectionConfig[string.Format("{0}-ua-order", className)]; - var keys = headers.Keys; + List orders = DetectionConfig[string.Format("{0}-ua-order", className)]; + Dictionary.KeyCollection keys = headers.Keys; Regex reg = new Regex("^x-", RegexOptions.IgnoreCase); - foreach (var key in keys) + foreach (string key in keys.Where(key => reg.IsMatch(key)).Where(key => !orders.Contains(key))) { - if (reg.IsMatch(key)) - { - if (!orders.Contains(key)) - { - orders.Add(key); - } - } + orders.Add(key); } - foreach (var item in orders) + for (int index = 0; index < orders.Count; index++) { - if (headers.ContainsKey(item)) + string item = orders[index]; + if (!headers.ContainsKey(item)) continue; + dynamic id = GetMatch("user-agent", headers[item], className, item, className); + if (id is bool) continue; + dynamic extra = FindById(id); + if (extra != null) { - dynamic id = getMatch("user-agent", headers[item], className, item, className); - if (!(id is Boolean)) - { - var extra = findById(id); - if (extra != null) - { - return extra; - } - } + return extra; } } return false; @@ -71,9 +60,9 @@ public dynamic matchExtra(string className, Dictionary headers) /// /// string id /// array device on success, false otherwise - public dynamic findById(string id) + public dynamic FindById(string id) { - return Store.read(string.Format("Extra_{0}", id)); + return _store.Read(string.Format("Extra_{0}", id)); } @@ -82,9 +71,9 @@ public dynamic findById(string id) /// /// headers A key => value array of sanitized http headers /// array Extra on success, false otherwise - public dynamic matchLanguage(Dictionary headers) + public dynamic MatchLanguage(Dictionary headers) { - var extra = new Dictionary(); + Dictionary extra = new Dictionary(); // Mock up a fake Extra for merge into detection reply. extra["_id"] = 0; extra.Add("Extra", new Dictionary()); @@ -94,40 +83,24 @@ public dynamic matchLanguage(Dictionary headers) // Try directly from http header first if (headers.ContainsKey("language")) { - var candidate = headers["language"]; - if (detectionLanguages.ContainsKey(candidate)) + dynamic candidate = headers["language"]; + if (DetectionLanguages.ContainsKey(candidate)) { extra["Extra"]["hd_specs"]["general_language"] = candidate; - extra["Extra"]["hd_specs"]["general_language_full"] = detectionLanguages[candidate]; + extra["Extra"]["hd_specs"]["general_language_full"] = DetectionLanguages[candidate]; return extra; } } - List checkOrder = detectionConfig["language-ua-order"]; - foreach (var item in headers) - { - checkOrder.Add(item.Key); - } + List checkOrder = DetectionConfig["language-ua-order"]; + checkOrder.AddRange(headers.Select(item => item.Key)); - var languageList = detectionLanguages; - foreach (var item in checkOrder) + Dictionary languageList = DetectionLanguages; + foreach (KeyValuePair languageItem in from item in checkOrder where headers.ContainsKey(item) select headers[item] into agent where !string.IsNullOrEmpty(agent) from languageItem in languageList where Regex.IsMatch(agent, string.Format("[; \\(]{0}[; \\)]", languageItem.Key)) select languageItem) { - if (headers.ContainsKey(item)) - { - var agent = headers[item]; - if (!string.IsNullOrEmpty(agent)) - { - foreach (var languageItem in languageList) - { - if (Regex.IsMatch(agent, string.Format("[; \\(]{0}[; \\)]", languageItem.Key))) - { - extra["Extra"]["hd_specs"]["general_language"] = languageItem.Key; - extra["Extra"]["hd_specs"]["general_language_full"] = languageItem.Value; - return extra; - } - } - } - } + extra["Extra"]["hd_specs"]["general_language"] = languageItem.Key; + extra["Extra"]["hd_specs"]["general_language_full"] = languageItem.Value; + return extra; } return false; } @@ -144,16 +117,16 @@ public dynamic matchLanguage(Dictionary headers) /// /// string specs The specs we want to check. /// boolean false if these specs can not run the detected OS, true otherwise. - public bool verifyPlatform(dynamic specs = null) + public bool VerifyPlatform(dynamic specs = null) { - var platform = data; + Dictionary platform = _data; - var platformName = platform["Extra"]["hd_specs"]["general_platform"].Trim().ToLower(); - var platformVersion = platform["Extra"]["hd_specs"]["general_platform_version"].Trim().ToLower(); + dynamic platformName = platform["Extra"]["hd_specs"]["general_platform"].Trim().ToLower(); + dynamic platformVersion = platform["Extra"]["hd_specs"]["general_platform_version"].Trim().ToLower(); - var devicePlatformName = specs["general_platform"].Trim().ToLower(); - var devicePlatformVersionMin = specs["general_platform_version"].Trim().ToLower(); - var devicePlatformVersionMax = specs["general_platform_version_max"].Trim().ToLower(); + dynamic devicePlatformName = specs["general_platform"].Trim().ToLower(); + dynamic devicePlatformVersionMin = specs["general_platform_version"].Trim().ToLower(); + dynamic devicePlatformVersionMax = specs["general_platform_version_max"].Trim().ToLower(); // Its possible that we didnt pickup the platform correctly or the device has no platform info // Return true in this case because we cant give a concrete false (it might run this version). @@ -167,11 +140,11 @@ public bool verifyPlatform(dynamic specs = null) // Detected version is lower than the min version - so definetly false. - if (!string.IsNullOrEmpty(platformVersion) && !string.IsNullOrEmpty(devicePlatformVersionMin) && comparePlatformVersions(platformVersion, devicePlatformVersionMin) <= -1) + if (!string.IsNullOrEmpty(platformVersion) && !string.IsNullOrEmpty(devicePlatformVersionMin) && ComparePlatformVersions(platformVersion, devicePlatformVersionMin) <= -1) return false; // Detected version is greater than the max version - so definetly false. - if (!string.IsNullOrEmpty(platformVersion) && !string.IsNullOrEmpty(devicePlatformVersionMax) && comparePlatformVersions(platformVersion, devicePlatformVersionMax) >= 1) + if (!string.IsNullOrEmpty(platformVersion) && !string.IsNullOrEmpty(devicePlatformVersionMax) && ComparePlatformVersions(platformVersion, devicePlatformVersionMax) >= 1) return false; // Maybe Ok .. @@ -187,14 +160,14 @@ public bool verifyPlatform(dynamic specs = null) /// /// string versionNumber /// array of ('major' => x, 'minor' => y and 'point' => z) on success, null otherwise - public Dictionary breakVersionApart(string versionNumber) + public Dictionary BreakVersionApart(string versionNumber) { - var tmp = (versionNumber + ".0.0.0").Split(new string[] { "." }, 4, StringSplitOptions.RemoveEmptyEntries); - reply = new Dictionary(); - reply["major"] = !string.IsNullOrEmpty(tmp[0]) ? tmp[0] : "0"; - reply["minor"] = !string.IsNullOrEmpty(tmp[1]) ? tmp[1] : "0"; - reply["point"] = !string.IsNullOrEmpty(tmp[2]) ? tmp[2] : "0"; - return reply; + string[] tmp = (versionNumber + ".0.0.0").Split(new string[] { "." }, 4, StringSplitOptions.RemoveEmptyEntries); + Reply = new Dictionary(); + Reply["major"] = !string.IsNullOrEmpty(tmp[0]) ? tmp[0] : "0"; + Reply["minor"] = !string.IsNullOrEmpty(tmp[1]) ? tmp[1] : "0"; + Reply["point"] = !string.IsNullOrEmpty(tmp[2]) ? tmp[2] : "0"; + return Reply; } /// @@ -203,21 +176,22 @@ public Dictionary breakVersionApart(string versionNumber) /// string $a Generally a number, but might be a string /// string $b Generally a number, but might be a string /// int - public int compareSmartly(string a, string b) + public int CompareSmartly(string a, string b) { return (IsNumeric(a) && IsNumeric(b)) ? (Convert.ToInt32(a) - Convert.ToInt32(b)) : string.Compare(a, b); } - static readonly Regex _isNumericRegex = + static readonly Regex IsNumericRegex = new Regex("^(" + /*Hex*/ @"0x[0-9a-f]+" + "|" + /*Bin*/ @"0b[01]+" + "|" + /*Oct*/ @"0[0-7]*" + "|" + /*Dec*/ @"((?!0)|[-+]|(?=0+\.))(\d*\.)?\d+(e\d+)?" + ")$"); - bool IsNumeric(string value) + + static bool IsNumeric(string value) { - return _isNumericRegex.IsMatch(value); + return IsNumericRegex.IsMatch(value); } @@ -227,18 +201,18 @@ bool IsNumeric(string value) /// string $va Version A /// string $vb Version B /// < 0 if a < b, 0 if a == b and > 0 if a > b : Also returns 0 if data is absent from either. - public int comparePlatformVersions(string va, string vb) + public int ComparePlatformVersions(string va, string vb) { if (string.IsNullOrEmpty(va) || string.IsNullOrEmpty(vb)) { return 0; } - var versionA = breakVersionApart(va); - var versionB = breakVersionApart(vb); + Dictionary versionA = BreakVersionApart(va); + Dictionary versionB = BreakVersionApart(vb); - var major = compareSmartly(versionA["major"], versionB["major"]); - var minor = compareSmartly(versionA["minor"], versionB["minor"]); - var point = compareSmartly(versionA["point"], versionB["point"]); + dynamic major = CompareSmartly(versionA["major"], versionB["major"]); + dynamic minor = CompareSmartly(versionA["minor"], versionB["minor"]); + dynamic point = CompareSmartly(versionA["point"], versionB["point"]); if (major != 0) return major; if (minor != 0) return minor; diff --git a/HandsetDetectionAPI/HDStore.cs b/HandsetDetectionAPI/HDStore.cs index 7ae18db1..4fbc42b9 100644 --- a/HandsetDetectionAPI/HDStore.cs +++ b/HandsetDetectionAPI/HDStore.cs @@ -9,46 +9,46 @@ namespace HandsetDetectionAPI { - public class HDStore : HDBase + public class HdStore : HdBase { - public string dirname = "hd40store"; - string path = ""; - public static string directory = ""; + public string Dirname = "hd40store"; + string _path = ""; + public static string Directory = ""; public string StoreDirectory { get { - if (!string.IsNullOrEmpty(directory) && !Directory.Exists(directory)) + if (!string.IsNullOrEmpty(Directory) && !System.IO.Directory.Exists(Directory)) { - Directory.CreateDirectory(directory); + System.IO.Directory.CreateDirectory(Directory); } - return directory; + return Directory; } } - private HDCache _Cache = null; + private HdCache _cache = null; /*** * * Singleton object creation code from http://csharpindepth.com/Articles/General/Singleton.aspx * **/ - private static readonly HDStore instance = new HDStore(); + private static readonly HdStore instance = new HdStore(); // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit - static HDStore() + static HdStore() { } - private HDStore() + private HdStore() { - this.path = ApplicationRootDirectory; - directory = this.path + "\\" + this.dirname; - this._Cache = new HDCache(); + _path = ApplicationRootDirectory; + Directory = _path + "\\" + Dirname; + _cache = new HdCache(); } - public static HDStore Instance + public static HdStore Instance { get { @@ -60,28 +60,23 @@ public static HDStore Instance /// Sets the path to the root directory for storage operations, optionally creating the storage directory in it. /// /// - /// - public void setPath(string path = null, bool IsCreateDirectory = false) + /// + public void SetPath(string path = null, bool isCreateDirectory = false) { - this.path = string.IsNullOrEmpty(path) ? AppDomain.CurrentDomain.BaseDirectory : path;//dirname(__FILE__) - directory = this.path + "\\" + this.dirname; - config["filesdir"] = path; - if (IsCreateDirectory) + this._path = string.IsNullOrEmpty(path) ? AppDomain.CurrentDomain.BaseDirectory : path;//dirname(__FILE__) + Directory = _path + "\\" + Dirname; + Config["filesdir"] = path; + if (!isCreateDirectory) return; + if (System.IO.Directory.Exists(StoreDirectory)) return; + try { - - if (!Directory.Exists(this.StoreDirectory)) - { - try - { - Directory.CreateDirectory(this.StoreDirectory); - } - catch (Exception) - { - throw new Exception("Error : Failed to create storage directory at (" + this.StoreDirectory + "). Check permissions."); + System.IO.Directory.CreateDirectory(StoreDirectory); + } + catch (Exception) + { + throw new Exception("Error : Failed to create storage directory at (" + StoreDirectory + "). Check permissions."); - } - } } } @@ -91,7 +86,7 @@ public void setPath(string path = null, bool IsCreateDirectory = false) /// /// /// - public bool write(string key, Dictionary data) + public bool Write(string key, Dictionary data) { if (!data.Any()) { @@ -103,7 +98,7 @@ public bool write(string key, Dictionary data) return false; } - return this._Cache.write(key, data).Any(); + return _cache.Write(key, data).Any(); } @@ -115,14 +110,10 @@ public bool write(string key, Dictionary data) /// true on success, false otherwise public bool store(string key, Dictionary data) { - var jss = new JavaScriptSerializer(); - jss.MaxJsonLength = this.maxJsonLength; - - string jsonstr = jss.Serialize(data); + string jsonstr = Jss.Serialize(data); try { - System.IO.File.WriteAllText(this.StoreDirectory + "//" + key + ".json", jsonstr); - + File.WriteAllText(StoreDirectory + "//" + key + ".json", jsonstr); } catch (Exception) { @@ -137,16 +128,16 @@ public bool store(string key, Dictionary data) /// /// Key to search for /// boolean true on success, false - public Dictionary read(string key) + public Dictionary Read(string key) { - Dictionary reply = this._Cache.read(key); + Dictionary reply = _cache.Read(key); if (reply != null && reply.Any()) return reply; - reply = this.fetch(key); + reply = Fetch(key); if (reply != null && reply.Any()) { - this._Cache.write(key, reply); + _cache.Write(key, reply); return reply; } else @@ -162,17 +153,10 @@ public Dictionary read(string key) /// key /// - public Dictionary fetch(string key) + public Dictionary Fetch(string key) { - var jss = new JavaScriptSerializer(); - jss.MaxJsonLength = this.maxJsonLength; - - string jsonText = System.IO.File.ReadAllText(this.StoreDirectory + "//" + key + ".json"); - if (string.IsNullOrEmpty(jsonText)) - { - return null; - } - return jss.Deserialize>(jsonText); + string jsonText = File.ReadAllText(StoreDirectory + "//" + key + ".json"); + return !string.IsNullOrEmpty(jsonText) ? Jss.Deserialize>(jsonText) : null; } /// @@ -180,31 +164,21 @@ public Dictionary fetch(string key) /// Used by localDevice* functions to iterate over all devies /// /// array All devices in one giant assoc array - public Dictionary fetchDevices() + public Dictionary FetchDevices() { - var jss = new JavaScriptSerializer(); - jss.MaxJsonLength = this.maxJsonLength; Dictionary data = new Dictionary(); List> dicList = new List>(); try { - string[] filePaths = Directory.GetFiles(this.StoreDirectory, "Device*.json"); - foreach (var item in filePaths) - { - string jsonText = System.IO.File.ReadAllText(item); - if (string.IsNullOrEmpty(jsonText)) - { - continue; - } - dicList.Add(jss.Deserialize>(jsonText)); - } + string[] filePaths = System.IO.Directory.GetFiles(StoreDirectory, "Device*.json"); + dicList.AddRange(from item in filePaths select File.ReadAllText(item) into jsonText where !string.IsNullOrEmpty(jsonText) select Jss.Deserialize>(jsonText)); data["devices"] = dicList; return data; } catch (Exception ex) { - reply = new Dictionary(); - this.setError(1, "Exception : " + ex.Message + " " + ex.StackTrace); + Reply = new Dictionary(); + SetError(1, "Exception : " + ex.Message + " " + ex.StackTrace); } return null; } @@ -215,7 +189,7 @@ public Dictionary fetchDevices() /// srcAbsName The fully qualified path and file name eg /tmp/sjjhas778hsjhh /// destName The key name inside the cache eg Device_19.json /// true on success, false otherwise - public bool moveIn(string srcAbsName, string destName) + public bool MoveIn(string srcAbsName, string destName) { // Move the file. try @@ -236,15 +210,15 @@ public bool moveIn(string srcAbsName, string destName) /// Cleans out the store - Use with caution /// /// true on success, false otherwise - public bool purge() + public bool Purge() { - string[] filePaths = Directory.GetFiles(this.StoreDirectory, "*.json"); - foreach (var item in filePaths) + string[] filePaths = System.IO.Directory.GetFiles(StoreDirectory, "*.json"); + foreach (string item in filePaths) { File.Delete(item); } - return this._Cache.purge(); + return _cache.Purge(); } } } diff --git a/HandsetDetectionAPI/HandsetDetectionType.cs b/HandsetDetectionAPI/HandsetDetectionType.cs index 75e9a6a1..080fecc7 100644 --- a/HandsetDetectionAPI/HandsetDetectionType.cs +++ b/HandsetDetectionAPI/HandsetDetectionType.cs @@ -8,7 +8,7 @@ namespace HandsetDetectionAPI { public enum HandsetDetectionType { - DETECTIONV4_STANDARD = 0, - DETECTIONV4_GENERIC = 1 + Detectionv4Standard = 0, + Detectionv4Generic = 1 } } diff --git a/HandsetDetectionAPI/testHD4.cs b/HandsetDetectionAPI/testHD4.cs index 42b107f1..d70a1d4a 100644 --- a/HandsetDetectionAPI/testHD4.cs +++ b/HandsetDetectionAPI/testHD4.cs @@ -12,27 +12,26 @@ namespace HandsetDetectionAPI { [TestFixture] - public class testHD4 + public class TestHd4 { - private HD4 objHD4; - string cloudConfig = "/hdCloudConfig.json"; //Cloud Config Name - string ultimateConfig = "/hdUltimateConfig.json"; // Ultimate Config Name - JavaScriptSerializer jss = new JavaScriptSerializer(); + private Hd4 _objHd4; + string _cloudConfig = "/hdCloudConfig.json"; //Cloud Config Name + string _ultimateConfig = "/hdUltimateConfig.json"; // Ultimate Config Name + JavaScriptSerializer _jss = new JavaScriptSerializer { MaxJsonLength = Hd4.MaxJsonLength }; - Dictionary devices = new Dictionary(); + Dictionary _devices = new Dictionary(); [SetUp] public void test0_initialSetup() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, cloudConfig); - jss.MaxJsonLength = objHD4.maxJsonLength; + _objHd4 = new Hd4(request, _cloudConfig); - if (!devices.ContainsKey("NokiaN95")) + if (!_devices.ContainsKey("NokiaN95")) { string noikaN95JsonText = "{\"general_vendor\":\"Nokia\",\"general_model\":\"N95\",\"general_platform\":\"Symbian\",\"general_platform_version\":\"9.2\",\"general_browser\":\"\",\"general_browser_version\":\"\",\"general_image\":\"nokian95-1403496370-0.gif\",\"general_aliases\":[],\"general_eusar\":\"0.50\",\"general_battery\":[\"Li-Ion 950 mAh\",\"BL-5F\"],\"general_type\":\"Mobile\",\"general_cpu\":[\"Dual ARM 11\",\"332MHz\"],\"design_formfactor\":\"Dual Slide\",\"design_dimensions\":\"99 x 53 x 21\",\"design_weight\":\"120\",\"design_antenna\":\"Internal\",\"design_keyboard\":\"Numeric\",\"design_softkeys\":\"2\",\"design_sidekeys\":[\"Volume\",\"Camera\"],\"display_type\":\"TFT\",\"display_color\":\"Yes\",\"display_colors\":\"16M\",\"display_size\":\"2.6\\\"\",\"display_x\":\"240\",\"display_y\":\"320\",\"display_other\":[],\"memory_internal\":[\"160MB\",\"64MB RAM\",\"256MB ROM\"],\"memory_slot\":[\"microSD\",\"8GB\",\"128MB\"],\"network\":[\"GSM850\",\"GSM900\",\"GSM1800\",\"GSM1900\",\"UMTS2100\",\"HSDPA2100\",\"Infrared\",\"Bluetooth 2.0\",\"802.11b\",\"802.11g\",\"GPRS Class 10\",\"EDGE Class 32\"],\"media_camera\":[\"5MP\",\"2592x1944\"],\"media_secondcamera\":[\"QVGA\"],\"media_videocapture\":[\"VGA@30fps\"],\"media_videoplayback\":[\"MPEG4\",\"H.263\",\"H.264\",\"3GPP\",\"RealVideo 8\",\"RealVideo 9\",\"RealVideo 10\"],\"media_audio\":[\"MP3\",\"AAC\",\"AAC+\",\"eAAC+\",\"WMA\"],\"media_other\":[\"Auto focus\",\"Video stabilizer\",\"Video calling\",\"Carl Zeiss optics\",\"LED Flash\"],\"features\":[\"Unlimited entries\",\"Multiple numbers per contact\",\"Picture ID\",\"Ring ID\",\"Calendar\",\"Alarm\",\"To-Do\",\"Document viewer\",\"Calculator\",\"Notes\",\"UPnP\",\"Computer sync\",\"VoIP\",\"Music ringtones (MP3)\",\"Vibration\",\"Phone profiles\",\"Speakerphone\",\"Accelerometer\",\"Voice dialing\",\"Voice commands\",\"Voice recording\",\"Push-to-Talk\",\"SMS\",\"MMS\",\"Email\",\"Instant Messaging\",\"Stereo FM radio\",\"Visual radio\",\"Dual slide design\",\"Organizer\",\"Word viewer\",\"Excel viewer\",\"PowerPoint viewer\",\"PDF viewer\",\"Predictive text input\",\"Push to talk\",\"Voice memo\",\"Games\"],\"connectors\":[\"USB\",\"MiniUSB\",\"3.5mm Audio\",\"TV Out\"],\"general_platform_version_max\":\"\",\"general_app\":\"\",\"general_app_version\":\"\",\"general_language\":\"\",\"display_ppi\":154,\"display_pixel_ratio\":\"1.0\",\"benchmark_min\":0,\"benchmark_max\":0,\"general_app_category\":\"\"}"; - devices.Add("NokiaN95", jss.Deserialize>(noikaN95JsonText)); + _devices.Add("NokiaN95", _jss.Deserialize>(noikaN95JsonText)); } } @@ -44,13 +43,13 @@ public void test0_initialSetup() [Test] public void test01_cloudConfigExists() { - string ApplicationPath = AppDomain.CurrentDomain.BaseDirectory; - if (ApplicationPath.IndexOf("\\bin") >= 0) + string applicationPath = AppDomain.CurrentDomain.BaseDirectory; + if (applicationPath.IndexOf("\\bin", StringComparison.Ordinal) >= 0) { - ApplicationPath = ApplicationPath.Substring(0, ApplicationPath.IndexOf("\\bin")); + applicationPath = applicationPath.Substring(0, applicationPath.IndexOf("\\bin", StringComparison.Ordinal)); } - bool IsFileExist = File.Exists(ApplicationPath + "/" + cloudConfig); - Assert.AreEqual(IsFileExist, true); + bool isFileExist = File.Exists(applicationPath + "/" + _cloudConfig); + Assert.AreEqual(isFileExist, true); } /// @@ -59,8 +58,8 @@ public void test01_cloudConfigExists() [Test] public void test02_deviceVendors() { - var result = objHD4.deviceVendors(); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceVendors(); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, reply["status"]); @@ -75,8 +74,8 @@ public void test02_deviceVendors() [Test] public void test03_deviceModels() { - var result = objHD4.deviceModels("Nokia"); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceModels("Nokia"); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, reply["status"]); Assert.AreEqual("OK", reply["message"]); @@ -90,12 +89,12 @@ public void test03_deviceModels() [Test] public void test04_deviceView() { - var result = objHD4.deviceView("Nokia", "N95"); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceView("Nokia", "N95"); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, reply["status"]); Assert.AreEqual("OK", reply["message"]); - Assert.AreEqual(jss.Serialize(devices["NokiaN95"]), jss.Serialize(reply["device"])); + Assert.AreEqual(_jss.Serialize(_devices["NokiaN95"]), _jss.Serialize(reply["device"])); } /// @@ -104,14 +103,14 @@ public void test04_deviceView() [Test] public void test05_deviceDeviceWhatHas() { - var result = objHD4.deviceWhatHas("design_dimensions", "101 x 44 x 16"); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceWhatHas("design_dimensions", "101 x 44 x 16"); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, reply["status"]); Assert.AreEqual("OK", reply["message"]); - var jsonString = jss.Serialize(reply["devices"]); + dynamic jsonString = _jss.Serialize(reply["devices"]); Assert.AreEqual(true, Regex.IsMatch(jsonString, "Asus")); Assert.AreEqual(true, Regex.IsMatch(jsonString, "V80")); @@ -127,11 +126,11 @@ public void test05_deviceDeviceWhatHas() [Test] public void test06_deviceDetectHTTPDesktop() { - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"} }; - var result = objHD4.deviceDetect(header); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, reply["status"]); Assert.AreEqual("OK", reply["message"]); @@ -144,12 +143,12 @@ public void test06_deviceDetectHTTPDesktop() [Test] public void test07_deviceDetectHTTPDesktopJunk() { - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ { "User-Agent","aksjakdjkjdaiwdidjkjdkawjdijwidawjdiajwdkawdjiwjdiawjdwidjwakdjajdkad"} }; - var result = objHD4.deviceDetect(header); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary reply = _objHd4.GetReply(); Assert.IsFalse(result); Assert.AreEqual(301, reply["status"]); Assert.AreEqual("Not Found", reply["message"]); @@ -162,12 +161,12 @@ public void test07_deviceDetectHTTPDesktopJunk() [Test] public void test08_deviceDetectHTTPWii() { - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Opera/9.30 (Nintendo Wii; U; ; 2047-7; es-Es)"} }; - var result = objHD4.deviceDetect(header); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, reply["status"]); Assert.AreEqual("OK", reply["message"]); @@ -180,11 +179,11 @@ public void test08_deviceDetectHTTPWii() [Test] public void test09_deviceDetectHTTP() { - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; en-gb) AppleWebKit/533.17.9 (KHTML, like Gecko)"} }; - var result = objHD4.deviceDetect(header); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, reply["status"]); @@ -211,13 +210,13 @@ public void test09_deviceDetectHTTP() [Test] public void test10_deviceDetectHTTPOtherHeader() { - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","blahblahblah"} }; header.Add("x-fish-header", "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; en-gb) AppleWebKit/533.17.9 (KHTML, like Gecko)"); - var result = objHD4.deviceDetect(header); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, reply["status"]); @@ -244,13 +243,13 @@ public void test10_deviceDetectHTTPOtherHeader() [Test] public void test11_deviceDetectHTTPHardwareInfo() { - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-gb) AppleWebKit/533.17.9 (KHTML, like Gecko)"} }; header.Add("x-local-hardwareinfo", "320:480:100:100"); - var result = objHD4.deviceDetect(header); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); @@ -279,13 +278,13 @@ public void test11_deviceDetectHTTPHardwareInfo() [Test] public void test12_deviceDetectHTTPHardwareInfoB() { - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-gb) AppleWebKit/533.17.9 (KHTML, like Gecko)"} }; header.Add("x-local-hardwareinfo", "320:480:100:72"); - var result = objHD4.deviceDetect(header); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); @@ -313,13 +312,13 @@ public void test12_deviceDetectHTTPHardwareInfoB() [Test] public void test13_deviceDetectHTTPHardwareInfoC() { - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_0 like Mac OS X; en-gb) AppleWebKit/533.17.9 (KHTML, like Gecko)"} }; header.Add("x-local-hardwareinfo", "320:480:200:1200"); - var result = objHD4.deviceDetect(header); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); @@ -347,13 +346,13 @@ public void test13_deviceDetectHTTPHardwareInfoC() [Test] public void test14_deviceDetectHTTPFBiOS() { - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Mobile/11D201 [FBAN/FBIOS;FBAV/9.0.0.25.31;FBBV/2102024;FBDV/iPhone6,2;FBMD/iPhone;FBSN/iPhone OS;FBSV/7.1.1;FBSS/2; FBCR/vodafoneIE;FBID/phone;FBLC/en_US;FBOP/5]"} }; header.Add("Accept-Language", "da, en-gb;q=0.8, en;q=0.7"); - var result = objHD4.deviceDetect(header); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); @@ -420,8 +419,8 @@ public void test15_deviceDetectBIAndroid() buildInfo.Add("ro.product_ship", "true"); - var result = objHD4.deviceDetect(buildInfo); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(buildInfo); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, reply["status"]); @@ -446,8 +445,8 @@ public void test16_deviceDetectBIiOS() buildInfo.Add("utsname.machine", "iphone4,1"); buildInfo.Add("utsname.brand", "Apple"); - var result = objHD4.deviceDetect(buildInfo); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(buildInfo); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); @@ -474,8 +473,8 @@ public void test17_deviceDetectWindowsPhone() buildInfo.Add("devicemanufacturer", "nokia"); buildInfo.Add("devicename", "RM-875"); - var result = objHD4.deviceDetect(buildInfo); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(buildInfo); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); @@ -506,11 +505,11 @@ public void test18_fetchArchive() // Note : request storage dir to be created if it does not exist. (with TRUE as 2nd param) HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); - HDStore Store = HDStore.Instance; - Store.purge(); - var result = objHD4.deviceFetchArchive(); - var reply = objHD4.getReply(); + _objHd4 = new Hd4(request, _ultimateConfig); + HdStore store = HdStore.Instance; + store.Purge(); + dynamic result = _objHd4.DeviceFetchArchive(); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); //TODO: to get no. bytes @@ -523,11 +522,11 @@ public void test18_fetchArchive() public void test19_ultimate_deviceVendors() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var result = objHD4.deviceVendors(); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceVendors(); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, reply["status"]); @@ -543,10 +542,10 @@ public void test19_ultimate_deviceVendors() public void test20_ultimate_deviceModels() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var result = objHD4.deviceModels("Nokia"); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceModels("Nokia"); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, reply["status"]); @@ -562,15 +561,15 @@ public void test20_ultimate_deviceModels() public void test21_ultimate_deviceView() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var result = objHD4.deviceView("Nokia", "N95"); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceView("Nokia", "N95"); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, reply["status"]); Assert.AreEqual("OK", reply["message"]); - Assert.AreEqual(jss.Serialize(devices["NokiaN95"]), jss.Serialize(reply["device"])); + Assert.AreEqual(_jss.Serialize(_devices["NokiaN95"]), _jss.Serialize(reply["device"])); } @@ -581,16 +580,16 @@ public void test21_ultimate_deviceView() public void test22_ultimate_deviceDeviceWhatHas() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var result = objHD4.deviceWhatHas("design_dimensions", "101 x 44 x 16"); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceWhatHas("design_dimensions", "101 x 44 x 16"); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, reply["status"]); Assert.AreEqual("OK", reply["message"]); - var jsonString = jss.Serialize(reply["devices"]); + dynamic jsonString = _jss.Serialize(reply["devices"]); Assert.AreEqual(true, Regex.IsMatch(jsonString, "Asus")); Assert.AreEqual(true, Regex.IsMatch(jsonString, "V80")); @@ -607,13 +606,13 @@ public void test22_ultimate_deviceDeviceWhatHas() public void test23_ultimate_deviceDetectHTTPDesktop() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"} }; - var result = objHD4.deviceDetect(header); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, reply["status"]); Assert.AreEqual("OK", reply["message"]); @@ -627,14 +626,14 @@ public void test23_ultimate_deviceDetectHTTPDesktop() public void test24_ultimate_deviceDetectHTTPDesktopJunk() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","aksjakdjkjdaiwdidjkjdkawjdijwidawjdiajwdkawdjiwjdiawjdwidjwakdjajdkad"} }; - var result = objHD4.deviceDetect(header); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary reply = _objHd4.GetReply(); Assert.IsFalse(result); Assert.AreEqual(301, reply["status"]); Assert.AreEqual("Not Found", reply["message"]); @@ -647,14 +646,14 @@ public void test24_ultimate_deviceDetectHTTPDesktopJunk() public void test25_ultimate_deviceDetectHTTPWii() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Opera/9.30 (Nintendo Wii; U; ; 2047-7; es-Es)"} }; - var result = objHD4.deviceDetect(header); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, reply["status"]); @@ -669,13 +668,13 @@ public void test25_ultimate_deviceDetectHTTPWii() public void test26_ultimate_deviceDetectHTTP() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; en-gb) AppleWebKit/533.17.9 (KHTML, like Gecko)"} }; - var result = objHD4.deviceDetect(header); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, reply["status"]); @@ -703,15 +702,15 @@ public void test26_ultimate_deviceDetectHTTP() public void test27_ultimate_deviceDetectHTTPOtherHeader() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","blahblahblah"} }; header.Add("x-fish-header", "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; en-gb) AppleWebKit/533.17.9 (KHTML, like Gecko)"); - var result = objHD4.deviceDetect(header); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, reply["status"]); @@ -739,15 +738,15 @@ public void test27_ultimate_deviceDetectHTTPOtherHeader() public void test28_ultimate_deviceDetectHTTPHardwareInfo() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-gb) AppleWebKit/533.17.9 (KHTML, like Gecko)"} }; header.Add("x-local-hardwareinfo", "320:480:100:100"); - var result = objHD4.deviceDetect(header); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); @@ -777,15 +776,15 @@ public void test28_ultimate_deviceDetectHTTPHardwareInfo() public void test29_ultimate_deviceDetectHTTPHardwareInfoB() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-gb) AppleWebKit/533.17.9 (KHTML, like Gecko)"} }; header.Add("x-local-hardwareinfo", "320:480:100:72"); - var result = objHD4.deviceDetect(header); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); @@ -814,15 +813,15 @@ public void test29_ultimate_deviceDetectHTTPHardwareInfoB() public void test30_ultimate_deviceDetectHTTPHardwareInfoC() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_0 like Mac OS X; en-gb) AppleWebKit/533.17.9 (KHTML, like Gecko)"} }; header.Add("x-local-hardwareinfo", "320:480:200:1200"); - var result = objHD4.deviceDetect(header); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); @@ -851,15 +850,15 @@ public void test30_ultimate_deviceDetectHTTPHardwareInfoC() public void test31_ultimate_deviceDetectHTTPFBiOS() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Mobile/11D201 [FBAN/FBIOS;FBAV/9.0.0.25.31;FBBV/2102024;FBDV/iPhone6,2;FBMD/iPhone;FBSN/iPhone OS;FBSV/7.1.1;FBSS/2; FBCR/vodafoneIE;FBID/phone;FBLC/en_US;FBOP/5]"} }; header.Add("Accept-Language", "da, en-gb;q=0.8, en;q=0.7"); - var result = objHD4.deviceDetect(header); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); @@ -894,7 +893,7 @@ public void test31_ultimate_deviceDetectHTTPFBiOS() public void test32_ultimate_deviceDetectBIAndroid() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); Dictionary buildInfo = new Dictionary(); buildInfo.Add("ro.build.PDA", "I9500XXUFNE7"); @@ -929,8 +928,8 @@ public void test32_ultimate_deviceDetectBIAndroid() buildInfo.Add("ro.product_ship", "true"); - var result = objHD4.deviceDetect(buildInfo); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(buildInfo); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, reply["status"]); @@ -952,14 +951,14 @@ public void test32_ultimate_deviceDetectBIAndroid() public void test33_ultimate_deviceDetectBIiOS() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); Dictionary buildInfo = new Dictionary(); buildInfo.Add("utsname.machine", "iphone4,1"); buildInfo.Add("utsname.brand", "Apple"); - var result = objHD4.deviceDetect(buildInfo); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(buildInfo); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); @@ -982,14 +981,14 @@ public void test33_ultimate_deviceDetectBIiOS() public void test34_ultimate_deviceDetectWindowsPhone() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); Dictionary buildInfo = new Dictionary(); buildInfo.Add("devicemanufacturer", "nokia"); buildInfo.Add("devicename", "RM-875"); - var result = objHD4.deviceDetect(buildInfo); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(buildInfo); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); @@ -1024,12 +1023,12 @@ public void test35_ultimate_community_fetchArchive() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); - HDStore Store = HDStore.Instance; - Store.purge(); - objHD4.isDownloadableFiles = true; - var result = objHD4.communityFetchArchive(); - var data = objHD4.getReply(); + _objHd4 = new Hd4(request, _ultimateConfig); + HdStore store = HdStore.Instance; + store.Purge(); + _objHd4.IsDownloadableFiles = true; + dynamic result = _objHd4.CommunityFetchArchive(); + Dictionary data = _objHd4.GetReply(); Assert.IsTrue(result); @@ -1044,15 +1043,15 @@ public void test35_ultimate_community_fetchArchive() public void test36_ultimate_community_deviceDetectHTTPDesktop() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"} }; - var result = objHD4.deviceDetect(header); - var data = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary data = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, data["status"]); @@ -1067,14 +1066,14 @@ public void test36_ultimate_community_deviceDetectHTTPDesktop() public void test37_ultimate_community_deviceDetectHTTPDesktopJunk() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","aksjakdjkjdaiwdidjkjdkawjdijwidawjdiajwdkawdjiwjdiawjdwidjwakdjajdkad"+DateTime.Now.Ticks.ToString()} }; - var result = objHD4.deviceDetect(header); - var data = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary data = _objHd4.GetReply(); Assert.IsFalse(result); Assert.AreEqual(301, data["status"]); @@ -1089,14 +1088,14 @@ public void test37_ultimate_community_deviceDetectHTTPDesktopJunk() public void test38_ultimate_community_deviceDetectHTTPWii() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Opera/9.30 (Nintendo Wii; U; ; 2047-7; es-Es)"} }; - var result = objHD4.deviceDetect(header); - var data = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary data = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, data["status"]); @@ -1112,14 +1111,14 @@ public void test38_ultimate_community_deviceDetectHTTPWii() public void test39_ultimate_community_deviceDetectHTTP() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; en-gb) AppleWebKit/533.17.9 (KHTML, like Gecko)"} }; - var result = objHD4.deviceDetect(header); - var data = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary data = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, data["status"]); @@ -1148,15 +1147,15 @@ public void test39_ultimate_community_deviceDetectHTTP() public void test40_ultimate_community_deviceDetectHTTPOtherHeader() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","blahblahblah"} }; header.Add("x-fish-header", "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; en-gb) AppleWebKit/533.17.9 (KHTML, like Gecko)"); - var result = objHD4.deviceDetect(header); - var data = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary data = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, data["status"]); @@ -1186,15 +1185,15 @@ public void test40_ultimate_community_deviceDetectHTTPOtherHeader() public void test41_ultimate_community_deviceDetectHTTPHardwareInfo() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-gb) AppleWebKit/533.17.9 (KHTML, like Gecko)"} }; header.Add("x-local-hardwareinfo", "320:480:100:100"); - var result = objHD4.deviceDetect(header); - var data = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary data = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, data["status"]); @@ -1224,15 +1223,15 @@ public void test41_ultimate_community_deviceDetectHTTPHardwareInfo() public void test42_ultimate_community_deviceDetectHTTPHardwareInfoB() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-gb) AppleWebKit/533.17.9 (KHTML, like Gecko)"} }; header.Add("x-local-hardwareinfo", "320:480:100:72"); - var result = objHD4.deviceDetect(header); - var data = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary data = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, data["status"]); @@ -1260,15 +1259,15 @@ public void test42_ultimate_community_deviceDetectHTTPHardwareInfoB() public void test43_ultimate_community_deviceDetectHTTPHardwareInfoC() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_0 like Mac OS X; en-gb) AppleWebKit/533.17.9 (KHTML, like Gecko)"} }; header.Add("x-local-hardwareinfo", "320:480:200:1200"); - var result = objHD4.deviceDetect(header); - var data = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary data = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, data["status"]); @@ -1296,15 +1295,15 @@ public void test43_ultimate_community_deviceDetectHTTPHardwareInfoC() public void test44_ultimate_community_deviceDetectHTTPFBiOS() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var header = new Dictionary(){ + Dictionary header = new Dictionary(){ {"User-Agent","Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_1 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Mobile/11D201 [FBAN/FBIOS;FBAV/9.0.0.25.31;FBBV/2102024;FBDV/iPhone6,2;FBMD/iPhone;FBSN/iPhone OS;FBSV/7.1.1;FBSS/2; FBCR/vodafoneIE;FBID/phone;FBLC/en_US;FBOP/5]"} }; header.Add("Accept-Language", "da, en-gb;q=0.8, en;q=0.7"); - var result = objHD4.deviceDetect(header); - var data = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(header); + Dictionary data = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, data["status"]); @@ -1371,10 +1370,10 @@ public void test45_ultimate_community_deviceDetectBIAndroid() buildInfo.Add("ro.product_ship", "true"); HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); - var result = objHD4.deviceDetect(buildInfo); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(buildInfo); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); Assert.AreEqual(0, reply["status"]); @@ -1396,15 +1395,15 @@ public void test45_ultimate_community_deviceDetectBIAndroid() public void test46_ultimate_community_deviceDetectBIiOS() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); Dictionary buildInfo = new Dictionary(); buildInfo.Add("utsname.machine", "iphone4,1"); buildInfo.Add("utsname.brand", "Apple"); - var result = objHD4.deviceDetect(buildInfo); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(buildInfo); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); @@ -1427,14 +1426,14 @@ public void test46_ultimate_community_deviceDetectBIiOS() public void test47_ultimate_community_deviceDetectWindowsPhone() { HttpRequest request = new HttpRequest(null, "http://localhost", null); - objHD4 = new HD4(request, ultimateConfig); + _objHd4 = new Hd4(request, _ultimateConfig); Dictionary buildInfo = new Dictionary(); buildInfo.Add("devicemanufacturer", "nokia"); buildInfo.Add("devicename", "RM-875"); - var result = objHD4.deviceDetect(buildInfo); - var reply = objHD4.getReply(); + bool result = _objHd4.DeviceDetect(buildInfo); + Dictionary reply = _objHd4.GetReply(); Assert.IsTrue(result); diff --git a/HandsetDetectionAPI/testHDCache.cs b/HandsetDetectionAPI/testHDCache.cs index 95c0ead6..ad3c6f44 100644 --- a/HandsetDetectionAPI/testHDCache.cs +++ b/HandsetDetectionAPI/testHDCache.cs @@ -7,22 +7,22 @@ namespace HandsetDetectionAPI { - public class testHDCache + public class TestHdCache { - private HDCache objCache; + private HdCache _objCache; - Dictionary testData = new Dictionary(); + Dictionary _testData = new Dictionary(); [SetUp] - public void testSetupData() + public void TestSetupData() { - objCache = new HDCache(); - if (testData.Count == 0) + _objCache = new HdCache(); + if (_testData.Count == 0) { - testData.Add("roses", "red"); - testData.Add("fish", "blue"); - testData.Add("sugar", "sweet"); - testData.Add("number", "4"); + _testData.Add("roses", "red"); + _testData.Add("fish", "blue"); + _testData.Add("sugar", "sweet"); + _testData.Add("number", "4"); } } @@ -30,11 +30,11 @@ public void testSetupData() public void test48_A() { string key = DateTime.Now.Ticks.ToString(); - objCache.write(key, testData); + _objCache.Write(key, _testData); - var reply = objCache.read(key); + var reply = _objCache.Read(key); - Assert.AreEqual(testData, reply); + Assert.AreEqual(_testData, reply); } [Test] @@ -46,14 +46,14 @@ public void test49_Volume() for (int i = 0; i < 10000; i++) { key = string.Format("test{0}_{1}", DateTime.Now.Ticks, i); - objCache.write(key, testData); + _objCache.Write(key, _testData); lstkeys.Add(key); } foreach (var objKey in lstkeys) { - var reply = objCache.read(objKey); - Assert.AreEqual(reply, testData); + var reply = _objCache.Read(objKey); + Assert.AreEqual(reply, _testData); } } } diff --git a/HandsetDetectionAPI/testHDDevice.cs b/HandsetDetectionAPI/testHDDevice.cs index d71b61f4..4078ea45 100644 --- a/HandsetDetectionAPI/testHDDevice.cs +++ b/HandsetDetectionAPI/testHDDevice.cs @@ -13,31 +13,31 @@ namespace HandsetDetectionAPI // To perform tests we need to setup the environment by populating the the Storage layer with device specs. // So install the latest community edition so there is something to work with. - public class testHDDevice + public class TestHdDevice { - private HDStore Store; - private HDDevice Device; + private HdStore _store; + private HdDevice _device; - private static bool IsCommunitySetupDone = true; - Dictionary headers = new Dictionary() { + private static bool _isCommunitySetupDone = true; + Dictionary _headers = new Dictionary() { {"User-Agent","Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like Mac OS X; en-gb) AppleWebKit/533.17.9 (KHTML, like Gecko)"}}; /// /// Setup community edition for tests. Takes 60s or so to download and install. /// [SetUp] - public void setUpBeforeClass() + public void SetUpBeforeClass() { - if (IsCommunitySetupDone) + if (_isCommunitySetupDone) { HttpRequest request = new HttpRequest(null, "http://localhost", null); - HD4 objHD4 = new HD4(request, "/hdCloudConfig.json"); + Hd4 objHd4 = new Hd4(request, "/hdCloudConfig.json"); string directoryPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); string filePath = directoryPath + "\\" + "communityTest.zip"; - Store = HDStore.Instance; - Store.setPath(directoryPath, true); - objHD4.communityFetchArchive(); - IsCommunitySetupDone = false; + _store = HdStore.Instance; + _store.SetPath(directoryPath, true); + objHd4.CommunityFetchArchive(); + _isCommunitySetupDone = false; } } @@ -48,27 +48,27 @@ public void setUpBeforeClass() [Test] public void test57_tearDownAfterClass() { - Store = HDStore.Instance; - Store.purge(); + _store = HdStore.Instance; + _store.Purge(); } [Test] public void test55_IsHelperUsefulTrue() { - Device = new HDDevice(); - Store.setPath("C://APIData"); + _device = new HdDevice(); + _store.SetPath("C://APIData"); - var result = Device.isHelperUseful(headers); + var result = _device.IsHelperUseful(_headers); Assert.IsTrue(result); } [Test] public void test56_IsHelperUsefulFalse() { - Device = new HDDevice(); - Store.setPath("C://APIData"); - headers["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"; - var result = Device.isHelperUseful(headers); + _device = new HdDevice(); + _store.SetPath("C://APIData"); + _headers["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36"; + var result = _device.IsHelperUseful(_headers); Assert.IsFalse(result); } diff --git a/HandsetDetectionAPI/testHDStore.cs b/HandsetDetectionAPI/testHDStore.cs index 6f671e9b..517bb0bb 100644 --- a/HandsetDetectionAPI/testHDStore.cs +++ b/HandsetDetectionAPI/testHDStore.cs @@ -9,24 +9,24 @@ namespace HandsetDetectionAPI { - public class testHDStore + public class TestHdStore { - JavaScriptSerializer jss = new JavaScriptSerializer(); - private HDStore Store; - private HDCache objCache; - Dictionary testData = new Dictionary(); + JavaScriptSerializer _jss = new JavaScriptSerializer(); + private HdStore _store; + private HdCache _objCache; + Dictionary _testData = new Dictionary(); [SetUp] - public void testSetupData() + public void TestSetupData() { - Store = HDStore.Instance; - objCache = new HDCache(); - if (testData.Count == 0) + _store = HdStore.Instance; + _objCache = new HdCache(); + if (_testData.Count == 0) { - testData.Add("roses", "red"); - testData.Add("fish", "blue"); - testData.Add("sugar", "sweet"); - testData.Add("number", "4"); + _testData.Add("roses", "red"); + _testData.Add("fish", "blue"); + _testData.Add("sugar", "sweet"); + _testData.Add("number", "4"); } } @@ -37,18 +37,18 @@ public void testSetupData() public void test50_ReadWrite() { string key = "storeKey" + DateTime.Now.Ticks; - Store.write(key, testData); + _store.Write(key, _testData); - var data = Store.read(key); + var data = _store.Read(key); - Assert.AreEqual(testData, data); + Assert.AreEqual(_testData, data); - var cacheData = objCache.read(key); + var cacheData = _objCache.Read(key); - Assert.AreEqual(testData, cacheData); + Assert.AreEqual(_testData, cacheData); - bool IsExists = System.IO.File.Exists(Store.StoreDirectory + "/" + key + ".json"); - Assert.IsTrue(IsExists); + bool isExists = System.IO.File.Exists(_store.StoreDirectory + "/" + key + ".json"); + Assert.IsTrue(isExists); } @@ -59,16 +59,16 @@ public void test50_ReadWrite() public void test51_StoreFetch() { string key = "storeKey2" + DateTime.Now.Ticks; - Store.store(key, testData); + _store.store(key, _testData); - var cahceData = objCache.read(key); - Assert.AreNotEqual(testData, cahceData); + var cahceData = _objCache.Read(key); + Assert.AreNotEqual(_testData, cahceData); - var storeData = Store.fetch(key); - Assert.AreEqual(testData, storeData); + var storeData = _store.Fetch(key); + Assert.AreEqual(_testData, storeData); - bool IsExists = System.IO.File.Exists(Store.StoreDirectory + "/" + key + ".json"); - Assert.IsTrue(IsExists); + bool isExists = System.IO.File.Exists(_store.StoreDirectory + "/" + key + ".json"); + Assert.IsTrue(isExists); } /// @@ -77,10 +77,10 @@ public void test51_StoreFetch() [Test] public void test52_Purge() { - var lstFiles = Directory.GetFiles(Store.StoreDirectory, "*.json"); + var lstFiles = Directory.GetFiles(_store.StoreDirectory, "*.json"); Assert.IsNotEmpty(lstFiles); - Store.purge(); - var lstFiles1 = Directory.GetFiles(Store.StoreDirectory, "*.json"); + _store.Purge(); + var lstFiles1 = Directory.GetFiles(_store.StoreDirectory, "*.json"); Assert.IsEmpty(lstFiles1); } @@ -91,10 +91,10 @@ public void test52_Purge() public void test53_FetchDevices() { string key = "Device" + DateTime.Now.Ticks; - Store.store(key, testData); - var devices = Store.fetchDevices(); - Assert.AreEqual(devices["devices"][0], testData); - Store.purge(); + _store.store(key, _testData); + var devices = _store.FetchDevices(); + Assert.AreEqual(devices["devices"][0], _testData); + _store.Purge(); } @@ -104,24 +104,24 @@ public void test53_FetchDevices() [Test] public void test54_MoveIn() { - var jsonString = jss.Serialize(testData); + var jsonString = _jss.Serialize(_testData); string filesuffix = DateTime.Now.Ticks.ToString(); - string filePathFirst = Store.StoreDirectory + "/TemDevice" + filesuffix + ".json"; - string filePathSecond = Store.StoreDirectory + "/Temp/TemDevice" + filesuffix + ".json"; + string filePathFirst = _store.StoreDirectory + "/TemDevice" + filesuffix + ".json"; + string filePathSecond = _store.StoreDirectory + "/Temp/TemDevice" + filesuffix + ".json"; File.WriteAllText(filePathFirst, jsonString); - if (!Directory.Exists(Store.StoreDirectory + "/Temp")) + if (!Directory.Exists(_store.StoreDirectory + "/Temp")) { - Directory.CreateDirectory(Store.StoreDirectory + "/Temp"); + Directory.CreateDirectory(_store.StoreDirectory + "/Temp"); } - bool IsFileExist = File.Exists(filePathFirst); - bool IsSecondFileExist = File.Exists(filePathSecond); - Assert.IsTrue(IsFileExist); - Assert.IsFalse(IsSecondFileExist); - Store.moveIn(filePathFirst, filePathSecond); - IsFileExist = File.Exists(filePathFirst); - IsSecondFileExist = File.Exists(filePathSecond); - Assert.IsFalse(IsFileExist); - Assert.IsTrue(IsSecondFileExist); + bool isFileExist = File.Exists(filePathFirst); + bool isSecondFileExist = File.Exists(filePathSecond); + Assert.IsTrue(isFileExist); + Assert.IsFalse(isSecondFileExist); + _store.MoveIn(filePathFirst, filePathSecond); + isFileExist = File.Exists(filePathFirst); + isSecondFileExist = File.Exists(filePathSecond); + Assert.IsFalse(isFileExist); + Assert.IsTrue(isSecondFileExist); } @@ -131,9 +131,9 @@ public void test54_MoveIn() [Test] public void test55_Singleton() { - var store1 = HDStore.Instance; - var store2 = HDStore.Instance; - store1.setPath("tmp", true); + var store1 = HdStore.Instance; + var store2 = HdStore.Instance; + store1.SetPath("tmp", true); Assert.AreEqual(store2.StoreDirectory, store1.StoreDirectory); } diff --git a/HandsetDetectionAPIKit4/Benchmark.aspx.cs b/HandsetDetectionAPIKit4/Benchmark.aspx.cs index fbb2d180..2236f258 100644 --- a/HandsetDetectionAPIKit4/Benchmark.aspx.cs +++ b/HandsetDetectionAPIKit4/Benchmark.aspx.cs @@ -55,7 +55,7 @@ protected void Page_Load(dynamic sender, EventArgs e) { Response.Write("File error: " + ex.Message); } - var objHd = new HD4(Request); + var objHd = new Hd4(Request); FlyThrough(objHd); lblTotDetect.Text = TotalCount.ToString(); @@ -63,7 +63,7 @@ protected void Page_Load(dynamic sender, EventArgs e) lblDetectPerSec.Text = ((Convert.ToDouble(TotalCount) * 1000) / TotalMilliSec).ToString(CultureInfo.InvariantCulture); } - public void FlyThrough(HD4 objHd) + public void FlyThrough(Hd4 objHd) { var deviceModelList = new List(); TotalCount = 1; @@ -72,7 +72,7 @@ public void FlyThrough(HD4 objHd) stopwatch.Start(); foreach (var header in _headers) { - var result = objHd.deviceDetect(header); + var result = objHd.DeviceDetect(header); TotalCount++; } diff --git a/HandsetDetectionAPIKit4/Default.aspx.cs b/HandsetDetectionAPIKit4/Default.aspx.cs index 15113adc..0fb03394 100644 --- a/HandsetDetectionAPIKit4/Default.aspx.cs +++ b/HandsetDetectionAPIKit4/Default.aspx.cs @@ -13,13 +13,14 @@ namespace Web public partial class Default : System.Web.UI.Page { - public string configFile = "//hdUltimateConfig.json"; - public Dictionary config = new Dictionary(); - public HD4 objHD4; + public string ConfigFile = "//hdUltimateConfig.json"; + public Dictionary Config = new Dictionary(); + public Hd4 ObjHd4; protected void Page_Load(object sender, EventArgs e) { + // Ensure config file is setup - + //if (!File.Exists(Server.MapPath(configFile))) //{ // throw new Exception("Config file not found"); diff --git a/HandsetDetectionAPIKit4/HandsetWithNetwork.aspx.cs b/HandsetDetectionAPIKit4/HandsetWithNetwork.aspx.cs index 8ec43bfd..01ef0040 100644 --- a/HandsetDetectionAPIKit4/HandsetWithNetwork.aspx.cs +++ b/HandsetDetectionAPIKit4/HandsetWithNetwork.aspx.cs @@ -12,37 +12,37 @@ namespace Web { public partial class HandsetWithNetwork : System.Web.UI.Page { - public string configFile = "//hdUltimateConfig.json"; - public Dictionary config = new Dictionary(); - public HD4 objHD4; + public string ConfigFile = "//hdUltimateConfig.json"; + public Dictionary Config = new Dictionary(); + public Hd4 ObjHd4; protected void Page_Load(object sender, EventArgs e) { // Ensure config file is setup - if (!File.Exists(Server.MapPath(configFile))) + if (!File.Exists(Server.MapPath(ConfigFile))) { throw new Exception("Config file not found"); } var serializer = new JavaScriptSerializer(); - string jsonText = System.IO.File.ReadAllText(Server.MapPath(configFile)); - config = serializer.Deserialize>(jsonText); + string jsonText = System.IO.File.ReadAllText(Server.MapPath(ConfigFile)); + Config = serializer.Deserialize>(jsonText); - if (config["username"] == "your_api_username") + if (Config["username"] == "your_api_username") { throw new Exception("Please configure your username, secret and site_id"); } - objHD4 = new HD4(Request, configFile); + ObjHd4 = new Hd4(Request, ConfigFile); // What handset have this attribute ? Response.Write("

    Nokia Models

    "); - if (objHD4.deviceWhatHas("network","CDMA")) + if (ObjHd4.DeviceWhatHas("network","CDMA")) { - Response.Write(objHD4.getRawReply()); + Response.Write(ObjHd4.GetRawReply()); } else { - Response.Write(objHD4.getError()); + Response.Write(ObjHd4.GetError()); } Response.Write("

    "); } diff --git a/HandsetDetectionAPIKit4/Models.aspx.cs b/HandsetDetectionAPIKit4/Models.aspx.cs index 570fad12..6f315067 100644 --- a/HandsetDetectionAPIKit4/Models.aspx.cs +++ b/HandsetDetectionAPIKit4/Models.aspx.cs @@ -12,37 +12,37 @@ namespace Web { public partial class Models : System.Web.UI.Page { - public string configFile = "//hdUltimateConfig.json"; - public Dictionary config = new Dictionary(); - public HD4 objHD4; + public string ConfigFile = "//hdUltimateConfig.json"; + public Dictionary Config = new Dictionary(); + public Hd4 ObjHd4; protected void Page_Load(object sender, EventArgs e) { // Ensure config file is setup - if (!File.Exists(Server.MapPath(configFile))) + if (!File.Exists(Server.MapPath(ConfigFile))) { throw new Exception("Config file not found"); } var serializer = new JavaScriptSerializer(); - string jsonText = System.IO.File.ReadAllText(Server.MapPath(configFile)); - config = serializer.Deserialize>(jsonText); + string jsonText = System.IO.File.ReadAllText(Server.MapPath(ConfigFile)); + Config = serializer.Deserialize>(jsonText); - if (config["username"] == "your_api_username") + if (Config["username"] == "your_api_username") { throw new Exception("Please configure your username, secret and site_id"); } - objHD4 = new HD4(Request, configFile); + ObjHd4 = new Hd4(Request, ConfigFile); // Models example : Get a list of all models for a specific vendor Response.Write("

    Nokia Models

    "); - if (objHD4.deviceModels("Nokia")) + if (ObjHd4.DeviceModels("Nokia")) { - Response.Write(objHD4.getRawReply()); + Response.Write(ObjHd4.GetRawReply()); } else { - Response.Write(objHD4.getError()); + Response.Write(ObjHd4.GetError()); } Response.Write("

    "); } diff --git a/HandsetDetectionAPIKit4/ModelsProperties.aspx.cs b/HandsetDetectionAPIKit4/ModelsProperties.aspx.cs index 616f9670..6513eec6 100644 --- a/HandsetDetectionAPIKit4/ModelsProperties.aspx.cs +++ b/HandsetDetectionAPIKit4/ModelsProperties.aspx.cs @@ -12,37 +12,37 @@ namespace Web { public partial class ModelsProperties : System.Web.UI.Page { - public string configFile = "//hdUltimateConfig.json"; - public Dictionary config = new Dictionary(); - public HD4 objHD4; + public string ConfigFile = "//hdUltimateConfig.json"; + public Dictionary Config = new Dictionary(); + public Hd4 ObjHd4; protected void Page_Load(object sender, EventArgs e) { // Ensure config file is setup - if (!File.Exists(Server.MapPath(configFile))) + if (!File.Exists(Server.MapPath(ConfigFile))) { throw new Exception("Config file not found"); } var serializer = new JavaScriptSerializer(); - string jsonText = System.IO.File.ReadAllText(Server.MapPath(configFile)); - config = serializer.Deserialize>(jsonText); + string jsonText = System.IO.File.ReadAllText(Server.MapPath(ConfigFile)); + Config = serializer.Deserialize>(jsonText); - if (config["username"] == "your_api_username") + if (Config["username"] == "your_api_username") { throw new Exception("Please configure your username, secret and site_id"); } - objHD4 = new HD4(Request, configFile); + ObjHd4 = new Hd4(Request, ConfigFile); // View information for a specific handset Response.Write("

    Nokia N95 Properties

    "); - if (objHD4.deviceView("Nokia", "N95")) + if (ObjHd4.DeviceView("Nokia", "N95")) { - Response.Write(objHD4.getRawReply()); + Response.Write(ObjHd4.GetRawReply()); } else { - Response.Write(objHD4.getError()); + Response.Write(ObjHd4.GetError()); } Response.Write("

    "); } diff --git a/HandsetDetectionAPIKit4/SimpleDetect.aspx.cs b/HandsetDetectionAPIKit4/SimpleDetect.aspx.cs index 8713c456..70a8391d 100644 --- a/HandsetDetectionAPIKit4/SimpleDetect.aspx.cs +++ b/HandsetDetectionAPIKit4/SimpleDetect.aspx.cs @@ -13,27 +13,27 @@ namespace Web public partial class SimpleDetect : System.Web.UI.Page { - public string configFile = "//hdUltimateConfig.json"; - public Dictionary config = new Dictionary(); - public HD4 objHD4; + public string ConfigFile = "//hdUltimateConfig.json"; + public Dictionary Config = new Dictionary(); + public Hd4 ObjHd4; protected void Page_Load(object sender, EventArgs e) { // Ensure config file is setup - if (!File.Exists(Server.MapPath(configFile))) + if (!File.Exists(Server.MapPath(ConfigFile))) { throw new Exception("Config file not found"); } var serializer = new JavaScriptSerializer(); - string jsonText = System.IO.File.ReadAllText(Server.MapPath(configFile)); - config = serializer.Deserialize>(jsonText); + string jsonText = System.IO.File.ReadAllText(Server.MapPath(ConfigFile)); + Config = serializer.Deserialize>(jsonText); - if (config["username"] == "your_api_username") + if (Config["username"] == "your_api_username") { throw new Exception("Please configure your username, secret and site_id"); } - objHD4 = new HD4(Request, configFile); + ObjHd4 = new Hd4(Request, ConfigFile); // This manually sets the headers that a Nokia N95 would set. // Other agents you also might like to try diff --git a/HandsetDetectionAPIKit4/Vendors.aspx.cs b/HandsetDetectionAPIKit4/Vendors.aspx.cs index 3d8d0403..4980ad99 100644 --- a/HandsetDetectionAPIKit4/Vendors.aspx.cs +++ b/HandsetDetectionAPIKit4/Vendors.aspx.cs @@ -12,39 +12,39 @@ namespace Web { public partial class Sites : System.Web.UI.Page { - public string configFile = "//hdUltimateConfig.json"; - public Dictionary config = new Dictionary(); - public HD4 objHD4; + public string ConfigFile = "//hdUltimateConfig.json"; + public Dictionary Config = new Dictionary(); + public Hd4 ObjHd4; protected void Page_Load(object sender, EventArgs e) { // Ensure config file is setup - if (!File.Exists(Server.MapPath(configFile))) + if (!File.Exists(Server.MapPath(ConfigFile))) { throw new Exception("Config file not found"); } var serializer = new JavaScriptSerializer(); - string jsonText = System.IO.File.ReadAllText(Server.MapPath(configFile)); - config = serializer.Deserialize>(jsonText); + string jsonText = System.IO.File.ReadAllText(Server.MapPath(ConfigFile)); + Config = serializer.Deserialize>(jsonText); - if (config["username"] == "your_api_username") + if (Config["username"] == "your_api_username") { throw new Exception("Please configure your username, secret and site_id"); } - objHD4 = new HD4(Request, configFile); + ObjHd4 = new Hd4(Request, ConfigFile); /// Vendors example : Get a list of all vendors /// Response.Write("

    Vendors

    "); - if (objHD4.deviceVendors()) + if (ObjHd4.DeviceVendors()) { - Response.Write(objHD4.getRawReply()); + Response.Write(ObjHd4.GetRawReply()); } else { - Response.Write(objHD4.getError()); + Response.Write(ObjHd4.GetError()); } Response.Write("

    "); } From e01d3f3e646660c778fce84bb85b13c87aabd0ce Mon Sep 17 00:00:00 2001 From: Info Offbeat Date: Fri, 12 Feb 2016 16:13:27 +0530 Subject: [PATCH 3/5] API Chnages --- .gitignore | 1 + HandsetDetectionAPI/HD4.cs | 4 +- HandsetDetectionAPI/HDBase.cs | 149 +++++--- HandsetDetectionAPI/HDCache.cs | 32 +- HandsetDetectionAPI/HDDevice.cs | 7 +- HandsetDetectionAPI/HDExtra.cs | 4 +- HandsetDetectionAPI/HDStore.cs | 28 +- HandsetDetectionAPI/testHD4.cs | 2 +- HandsetDetectionAPI/testHDCache.cs | 4 +- HandsetDetectionAPI/testHDStore.cs | 8 +- HandsetDetectionAPIKit4/benchmarkData.txt | 4 +- HandsetDetectionAPIKit4/packages.config | 4 + .../fastJSON.2.1.14.0/fastJSON.2.1.14.0.nupkg | Bin 0 -> 61565 bytes packages/fastJSON.2.1.14.0/lib/history.txt | 330 ++++++++++++++++++ .../fastJSON.2.1.14.0/lib/net20/fastjson.dll | Bin 0 -> 38912 bytes .../fastJSON.2.1.14.0/lib/net35/fastjson.dll | Bin 0 -> 38912 bytes packages/fastJSON.2.1.14.0/lib/readme.md | 6 + packages/repositories.config | 1 + 18 files changed, 504 insertions(+), 80 deletions(-) create mode 100644 HandsetDetectionAPIKit4/packages.config create mode 100644 packages/fastJSON.2.1.14.0/fastJSON.2.1.14.0.nupkg create mode 100644 packages/fastJSON.2.1.14.0/lib/history.txt create mode 100644 packages/fastJSON.2.1.14.0/lib/net20/fastjson.dll create mode 100644 packages/fastJSON.2.1.14.0/lib/net35/fastjson.dll create mode 100644 packages/fastJSON.2.1.14.0/lib/readme.md diff --git a/.gitignore b/.gitignore index eed90e5d..d0626d8a 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,4 @@ __MACOSX/ .DS_Store !obj/ !bin/ +Report160126.vsp diff --git a/HandsetDetectionAPI/HD4.cs b/HandsetDetectionAPI/HD4.cs index b04310dd..eeade5b0 100644 --- a/HandsetDetectionAPI/HD4.cs +++ b/HandsetDetectionAPI/HD4.cs @@ -269,6 +269,8 @@ public bool DeviceWhatHas(string key, string value) /// true on success, false otherwise. Use getReply to inspect results on success. public bool DeviceDetect(Dictionary data = null) { + + int id = 0; if (data == null || !data.Any() || !data.ContainsKey("id")) { @@ -300,7 +302,7 @@ public bool DeviceDetect(Dictionary data = null) { IOrderedEnumerable headersKeys = requestBody.Values.Select(c => c).OrderBy(c => c); fastKey = Jss.Serialize(headersKeys).Replace(" ", ""); - Dictionary objReply = _cache.Read(fastKey); + Dictionary objReply = _cache.Read>(fastKey); if (objReply.Count > 0) { Reply = objReply; diff --git a/HandsetDetectionAPI/HDBase.cs b/HandsetDetectionAPI/HDBase.cs index 57a2fdcc..0351ee09 100644 --- a/HandsetDetectionAPI/HDBase.cs +++ b/HandsetDetectionAPI/HDBase.cs @@ -179,8 +179,24 @@ public void SetReply(Dictionary objReply) protected bool SetError(int status, string msg) { this.Error = msg; - Reply["status"] = status; - Reply["message"] = msg; + + if (Reply.ContainsKey("status")) + { + Reply["status"] = status; + } + else + { + Reply.Add("status", status); + } + + if (Reply.ContainsKey("message")) + { + Reply["message"] = msg; + } + else + { + Reply.Add("message", msg); + } return (status <= 0); } @@ -193,17 +209,22 @@ public string ExtraCleanStr(string str) { if (string.IsNullOrEmpty(str)) return string.Empty; - - for (int i = 0; i < ExtraUaFilterList.Count; i++) - { - for (int j = 0; j < ExtraUaFilterList[i].Length; j++) - { - str = str.Replace(ExtraUaFilterList[i][j], ' '); - } - } - - str = _reg.Replace(str, ""); - return Regex.Replace(str, @"\s+", ""); + StringBuilder b = new StringBuilder(str.ToLower()); + foreach (char c in _extraUaFilter) + { + b.Replace(c.ToString(), string.Empty); + } + //for (int i = 0; i < ExtraUaFilterList.Count; i++) + //{ + // for (int j = 0; j < ExtraUaFilterList[i].Length; j++) + // { + // str = str.Replace(ExtraUaFilterList[i][j], ' '); + // } + //} + + //str = _reg.Replace(str, ""); + //return Regex.Replace(str, @"\s+", ""); + return b.ToString(); } static Regex _reg = new Regex("[^(\x20-\x7F)]*", RegexOptions.Compiled); @@ -216,17 +237,22 @@ public string CleanStr(string str) { if (string.IsNullOrEmpty(str)) return string.Empty; - - for (int i = 0; i < DeviceUaFilterList.Count; i++) - { - for (int j = 0; j < DeviceUaFilterList[i].Length; j++) - { - str = str.Replace(DeviceUaFilterList[i][j], ' '); - } - } - - str = _reg.Replace(str, ""); - return Regex.Replace(str, @"\s+", ""); + StringBuilder b = new StringBuilder(str.ToLower()); + foreach (char c in _deviceUaFilter) + { + b.Replace(c.ToString(), string.Empty); + } + //for (int i = 0; i < DeviceUaFilterList.Count; i++) + //{ + // for (int j = 0; j < DeviceUaFilterList[i].Length; j++) + // { + // str = str.Replace(DeviceUaFilterList[i][j], ' '); + // } + //} + + //str = _reg.Replace(str, ""); + //return Regex.Replace(str, @"\s+", ""); + return b.ToString(); } /// @@ -243,7 +269,7 @@ protected bool Remote(string suburl, Dictionary data, string fi string request; string requestUrl = _apiBase + suburl; - int attempts = Config["retries"] + 1; + int attempts = Convert.ToInt32(Config["retries"]) + 1; int trys = 0; if (data == null || data.Count == 0) request = ""; @@ -455,31 +481,66 @@ public dynamic GetMatch(string header, string value, string subtree = "0", strin { return false; } - Dictionary branch = GetBranch(branchName); - - if (branch == null) - { - return false; - } + if (string.Compare(header, "user-agent", StringComparison.OrdinalIgnoreCase) == 0) { + Dictionary>> branch = GetBranch>>>(branchName); - foreach (KeyValuePair filter in branch.Select(order => order.Value).OfType>().SelectMany(filters => filters)) + if (branch == null) { - // ++f; - if (!value.Contains(filter.Key)) continue; + return false; + } - Dictionary matches = (Dictionary)filter.Value; - foreach (KeyValuePair match in matches.Where(match => value.Contains(match.Key))) + foreach (KeyValuePair>> orders in branch) + { + foreach (KeyValuePair> filters in orders.Value) { - DetectedRuleKey[className] = CleanStr(header) + ":" + CleanStr(filter.Key) + ":" + CleanStr(match.Key); - return match.Value; + // f++; + + if (value.IndexOf(filters.Key, StringComparison.OrdinalIgnoreCase) >= 0) + { + foreach (KeyValuePair matches in filters.Value) + { + // r++; + + if (value.IndexOf(matches.Key, StringComparison.OrdinalIgnoreCase) >= 0) + { + DetectedRuleKey[className] = CleanStr(header) + ":" + CleanStr(filters.Key) + ":" + CleanStr(matches.Key); + return matches.Value; + } + } + } } } + + //foreach (KeyValuePair filter in branch.Select(order => order.Value).OfType>().SelectMany(filters => filters)) + //{ + // // ++f; + // if (!(value.IndexOf(filter.Key, StringComparison.OrdinalIgnoreCase) > 0)) continue; + + // var matches = ((Dictionary)filter.Value).Where(match => value.IndexOf(match.Key, StringComparison.OrdinalIgnoreCase) > 0); + // foreach (KeyValuePair match in matches) + // { + // if (DetectedRuleKey.ContainsKey(className)) + // { + // DetectedRuleKey.Add(className, CleanStr(header) + ":" + CleanStr(filter.Key) + ":" + CleanStr(match.Key)); + // } + // else + // { + // DetectedRuleKey[className] = CleanStr(header) + ":" + CleanStr(filter.Key) + ":" + CleanStr(match.Key); + // } + // return match.Value; + // } + //} } else { + Dictionary branch = GetBranch>(branchName); + if (branch == null) + { + return false; + } if (branch.ContainsKey(value)) return branch[value]; return false; } @@ -493,15 +554,15 @@ public dynamic GetMatch(string header, string value, string subtree = "0", strin /// /// The name of the branch to find /// an assoc array on success, false otherwise. - public Dictionary GetBranch(string branchName) + public T GetBranch(string branchName) { if (Tree != null && (Tree.ContainsKey(branchName) && Tree[branchName] != null)) { - return Tree[branchName]; + return (T)Convert.ChangeType(Tree[branchName], typeof(T)); } - Dictionary tmp = _store.Read(branchName); - if (tmp == null) return null; + T tmp = _store.Read(branchName); + if (tmp == null) return default(T); Tree[branchName] = tmp; return tmp; @@ -537,7 +598,7 @@ public bool UseProxy { get { - return Config["use_proxy"]; + return Convert.ToBoolean(Config["use_proxy"]); } set { @@ -670,7 +731,7 @@ public int ReadTimeout protected string Log; protected Dictionary RawReply = null; protected Dictionary Tree = new Dictionary(); - + protected string Error = ""; diff --git a/HandsetDetectionAPI/HDCache.cs b/HandsetDetectionAPI/HDCache.cs index 0d35d1b5..088b30b7 100644 --- a/HandsetDetectionAPI/HDCache.cs +++ b/HandsetDetectionAPI/HDCache.cs @@ -29,33 +29,43 @@ public HdCache() _myCache = MemoryCache.Default; } - public Dictionary Write(string key, dynamic value) + public T Write(string key, T value) { - if (value != null && key != "") + + try { - string storethis = _jss.Serialize(value); - _myCache.Set(_prefix + key, storethis, _policy); - return value; + if (value != null && key != "") + { + // string storethis = _jss.Serialize(value); + _myCache.Set(_prefix + key, value, _policy); + return value; + } + else + { + return default(T); + } } - else + catch (Exception) { - return null; + + throw; } + } - public Dictionary Read(string key) + public T Read(string key) { try { - string fromCache = _myCache.Get(_prefix + key) as string; - if (fromCache != null) return _jss.Deserialize>(fromCache); + object fromCache = _myCache.Get(_prefix + key); + if (fromCache != null) return (T)Convert.ChangeType(fromCache, typeof(T)); } catch (Exception) { // Not in cache } - return null; + return default(T); } public bool Purge() diff --git a/HandsetDetectionAPI/HDDevice.cs b/HandsetDetectionAPI/HDDevice.cs index 6c86daf8..83717def 100644 --- a/HandsetDetectionAPI/HDDevice.cs +++ b/HandsetDetectionAPI/HDDevice.cs @@ -19,6 +19,7 @@ public class HdDevice : HdBase public HdDevice() { + _store = HdStore.Instance; _extra = new HdExtra(); } @@ -427,7 +428,7 @@ private void HardwareInfoOverlay(ref dynamic device, Dictionary private dynamic MatchDevice(Dictionary headers) { // Opera mini sometimes puts the vendor # model in the header - nice! ... sometimes it puts ? # ? in as well - if (headers.ContainsKey("x-operamini-phone") && headers["x-operamini-phone"].trim() != "? # ?") + if (headers.ContainsKey("x-operamini-phone") && headers["x-operamini-phone"].ToString() != "? # ?") { dynamic id = this.GetMatch("x-operamini-phone", headers["x-operamini-phone"], _detectionv4Standard, "x-operamini-phone", "device"); if (!(id is bool)) @@ -503,7 +504,7 @@ private dynamic MatchDevice(Dictionary headers) /// list of device on success, false otherwise public Dictionary FindById(string id) { - return _store.Read(string.Format("Device_{0}", id)); + return _store.Read>(string.Format("Device_{0}", id)); } /// @@ -812,7 +813,7 @@ private dynamic V4MatchHttpHeaders(Dictionary headers, string h /// a list of candidate devices which have this detection rule or false otherwise. private dynamic GetHighAccuracyCandidates() { - Dictionary branch = GetBranch("hachecks"); + var branch = GetBranch>>("hachecks"); dynamic ruleKey = DetectedRuleKey["device"]; if (branch.ContainsKey(ruleKey)) { diff --git a/HandsetDetectionAPI/HDExtra.cs b/HandsetDetectionAPI/HDExtra.cs index 479c0dff..30a6a1f2 100644 --- a/HandsetDetectionAPI/HDExtra.cs +++ b/HandsetDetectionAPI/HDExtra.cs @@ -62,7 +62,7 @@ public dynamic MatchExtra(string className, Dictionary headers) /// array device on success, false otherwise public dynamic FindById(string id) { - return _store.Read(string.Format("Extra_{0}", id)); + return _store.Read>(string.Format("Extra_{0}", id)); } @@ -102,7 +102,7 @@ public dynamic MatchLanguage(Dictionary headers) extra["Extra"]["hd_specs"]["general_language_full"] = languageItem.Value; return extra; } - return false; + return extra; } diff --git a/HandsetDetectionAPI/HDStore.cs b/HandsetDetectionAPI/HDStore.cs index 4fbc42b9..b878791c 100644 --- a/HandsetDetectionAPI/HDStore.cs +++ b/HandsetDetectionAPI/HDStore.cs @@ -128,21 +128,21 @@ public bool store(string key, Dictionary data) /// /// Key to search for /// boolean true on success, false - public Dictionary Read(string key) + public T Read(string key) { - Dictionary reply = _cache.Read(key); - if (reply != null && reply.Any()) + var reply = _cache.Read(key); + if (reply != null) return reply; - reply = Fetch(key); - if (reply != null && reply.Any()) + reply = Fetch(key); + if (reply != null) { _cache.Write(key, reply); return reply; } else { - return null; + return default(T); } } @@ -153,10 +153,20 @@ public Dictionary Read(string key) /// key /// - public Dictionary Fetch(string key) + public T Fetch(string key) { - string jsonText = File.ReadAllText(StoreDirectory + "//" + key + ".json"); - return !string.IsNullOrEmpty(jsonText) ? Jss.Deserialize>(jsonText) : null; + try + { + string jsonText = File.ReadAllText(StoreDirectory + "//" + key + ".json"); + return !string.IsNullOrEmpty(jsonText) ? Jss.Deserialize(jsonText) : default(T); + + } + catch (Exception) + { + + return default(T); + } + } /// diff --git a/HandsetDetectionAPI/testHD4.cs b/HandsetDetectionAPI/testHD4.cs index d70a1d4a..df60bb0b 100644 --- a/HandsetDetectionAPI/testHD4.cs +++ b/HandsetDetectionAPI/testHD4.cs @@ -30,7 +30,7 @@ public void test0_initialSetup() if (!_devices.ContainsKey("NokiaN95")) { - string noikaN95JsonText = "{\"general_vendor\":\"Nokia\",\"general_model\":\"N95\",\"general_platform\":\"Symbian\",\"general_platform_version\":\"9.2\",\"general_browser\":\"\",\"general_browser_version\":\"\",\"general_image\":\"nokian95-1403496370-0.gif\",\"general_aliases\":[],\"general_eusar\":\"0.50\",\"general_battery\":[\"Li-Ion 950 mAh\",\"BL-5F\"],\"general_type\":\"Mobile\",\"general_cpu\":[\"Dual ARM 11\",\"332MHz\"],\"design_formfactor\":\"Dual Slide\",\"design_dimensions\":\"99 x 53 x 21\",\"design_weight\":\"120\",\"design_antenna\":\"Internal\",\"design_keyboard\":\"Numeric\",\"design_softkeys\":\"2\",\"design_sidekeys\":[\"Volume\",\"Camera\"],\"display_type\":\"TFT\",\"display_color\":\"Yes\",\"display_colors\":\"16M\",\"display_size\":\"2.6\\\"\",\"display_x\":\"240\",\"display_y\":\"320\",\"display_other\":[],\"memory_internal\":[\"160MB\",\"64MB RAM\",\"256MB ROM\"],\"memory_slot\":[\"microSD\",\"8GB\",\"128MB\"],\"network\":[\"GSM850\",\"GSM900\",\"GSM1800\",\"GSM1900\",\"UMTS2100\",\"HSDPA2100\",\"Infrared\",\"Bluetooth 2.0\",\"802.11b\",\"802.11g\",\"GPRS Class 10\",\"EDGE Class 32\"],\"media_camera\":[\"5MP\",\"2592x1944\"],\"media_secondcamera\":[\"QVGA\"],\"media_videocapture\":[\"VGA@30fps\"],\"media_videoplayback\":[\"MPEG4\",\"H.263\",\"H.264\",\"3GPP\",\"RealVideo 8\",\"RealVideo 9\",\"RealVideo 10\"],\"media_audio\":[\"MP3\",\"AAC\",\"AAC+\",\"eAAC+\",\"WMA\"],\"media_other\":[\"Auto focus\",\"Video stabilizer\",\"Video calling\",\"Carl Zeiss optics\",\"LED Flash\"],\"features\":[\"Unlimited entries\",\"Multiple numbers per contact\",\"Picture ID\",\"Ring ID\",\"Calendar\",\"Alarm\",\"To-Do\",\"Document viewer\",\"Calculator\",\"Notes\",\"UPnP\",\"Computer sync\",\"VoIP\",\"Music ringtones (MP3)\",\"Vibration\",\"Phone profiles\",\"Speakerphone\",\"Accelerometer\",\"Voice dialing\",\"Voice commands\",\"Voice recording\",\"Push-to-Talk\",\"SMS\",\"MMS\",\"Email\",\"Instant Messaging\",\"Stereo FM radio\",\"Visual radio\",\"Dual slide design\",\"Organizer\",\"Word viewer\",\"Excel viewer\",\"PowerPoint viewer\",\"PDF viewer\",\"Predictive text input\",\"Push to talk\",\"Voice memo\",\"Games\"],\"connectors\":[\"USB\",\"MiniUSB\",\"3.5mm Audio\",\"TV Out\"],\"general_platform_version_max\":\"\",\"general_app\":\"\",\"general_app_version\":\"\",\"general_language\":\"\",\"display_ppi\":154,\"display_pixel_ratio\":\"1.0\",\"benchmark_min\":0,\"benchmark_max\":0,\"general_app_category\":\"\"}"; + string noikaN95JsonText = "{\"general_vendor\":\"Nokia\",\"general_model\":\"N95\",\"general_platform\":\"Symbian\",\"general_platform_version\":\"9.2\",\"general_browser\":\"\",\"general_browser_version\":\"\",\"general_image\":\"nokian95-1403496370-0.gif\",\"general_aliases\":[],\"general_eusar\":\"0.50\",\"general_battery\":[\"Li-Ion 950 mAh\",\"BL-5F\"],\"general_type\":\"Mobile\",\"general_cpu\":[\"Dual ARM 11\",\"332MHz\"],\"design_formfactor\":\"Dual Slide\",\"design_dimensions\":\"99 x 53 x 21\",\"design_weight\":\"120\",\"design_antenna\":\"Internal\",\"design_keyboard\":\"Numeric\",\"design_softkeys\":\"2\",\"design_sidekeys\":[\"Volume\",\"Camera\"],\"display_type\":\"TFT\",\"display_color\":\"Yes\",\"display_colors\":\"16M\",\"display_size\":\"2.6\\\"\",\"display_x\":\"240\",\"display_y\":\"320\",\"display_other\":[],\"memory_internal\":[\"160MB\",\"64MB RAM\",\"256MB ROM\"],\"memory_slot\":[\"microSD\",\"8GB\",\"128MB\"],\"network\":[\"GSM850\",\"GSM900\",\"GSM1800\",\"GSM1900\",\"UMTS2100\",\"HSDPA2100\",\"Infrared\",\"Bluetooth 2.0\",\"802.11b\",\"802.11g\",\"GPRS Class 10\",\"EDGE Class 32\"],\"media_camera\":[\"5MP\",\"2592x1944\"],\"media_secondcamera\":[\"QVGA\"],\"media_videocapture\":[\"VGA@30fps\"],\"media_videoplayback\":[\"MPEG4\",\"H.263\",\"H.264\",\"3GPP\",\"RealVideo 8\",\"RealVideo 9\",\"RealVideo 10\"],\"media_audio\":[\"MP3\",\"AAC\",\"AAC+\",\"eAAC+\",\"WMA\"],\"media_other\":[\"Auto focus\",\"Video stabilizer\",\"Video calling\",\"Carl Zeiss optics\",\"LED Flash\"],\"features\":[\"Unlimited entries\",\"Multiple numbers per contact\",\"Picture ID\",\"Ring ID\",\"Calendar\",\"Alarm\",\"To-Do\",\"Document viewer\",\"Calculator\",\"Notes\",\"UPnP\",\"Computer sync\",\"VoIP\",\"Music ringtones (MP3)\",\"Vibration\",\"Phone profiles\",\"Speakerphone\",\"Accelerometer\",\"Voice dialing\",\"Voice commands\",\"Voice recording\",\"Push-to-Talk\",\"SMS\",\"MMS\",\"Email\",\"Instant Messaging\",\"Stereo FM radio\",\"Visual radio\",\"Dual slide design\",\"Organizer\",\"Word viewer\",\"Excel viewer\",\"PowerPoint viewer\",\"PDF viewer\",\"Predictive text input\",\"Push to talk\",\"Voice memo\",\"Games\"],\"connectors\":[\"USB\",\"MiniUSB\",\"3.5mm Audio\",\"TV Out\"],\"general_platform_version_max\":\"\",\"general_app\":\"\",\"general_app_version\":\"\",\"general_language\":\"\",\"display_ppi\":154,\"display_pixel_ratio\":\"1.0\",\"benchmark_min\":0,\"benchmark_max\":0,\"general_app_category\":\"\",\"general_virtual\":0}"; _devices.Add("NokiaN95", _jss.Deserialize>(noikaN95JsonText)); } diff --git a/HandsetDetectionAPI/testHDCache.cs b/HandsetDetectionAPI/testHDCache.cs index ad3c6f44..eac27456 100644 --- a/HandsetDetectionAPI/testHDCache.cs +++ b/HandsetDetectionAPI/testHDCache.cs @@ -32,7 +32,7 @@ public void test48_A() string key = DateTime.Now.Ticks.ToString(); _objCache.Write(key, _testData); - var reply = _objCache.Read(key); + var reply = _objCache.Read>(key); Assert.AreEqual(_testData, reply); } @@ -52,7 +52,7 @@ public void test49_Volume() foreach (var objKey in lstkeys) { - var reply = _objCache.Read(objKey); + var reply = _objCache.Read>(objKey); Assert.AreEqual(reply, _testData); } } diff --git a/HandsetDetectionAPI/testHDStore.cs b/HandsetDetectionAPI/testHDStore.cs index 517bb0bb..d00e333a 100644 --- a/HandsetDetectionAPI/testHDStore.cs +++ b/HandsetDetectionAPI/testHDStore.cs @@ -39,11 +39,11 @@ public void test50_ReadWrite() string key = "storeKey" + DateTime.Now.Ticks; _store.Write(key, _testData); - var data = _store.Read(key); + var data = _store.Read>(key); Assert.AreEqual(_testData, data); - var cacheData = _objCache.Read(key); + var cacheData = _objCache.Read>(key); Assert.AreEqual(_testData, cacheData); @@ -61,10 +61,10 @@ public void test51_StoreFetch() string key = "storeKey2" + DateTime.Now.Ticks; _store.store(key, _testData); - var cahceData = _objCache.Read(key); + var cahceData = _objCache.Read>(key); Assert.AreNotEqual(_testData, cahceData); - var storeData = _store.Fetch(key); + var storeData = _store.Fetch>(key); Assert.AreEqual(_testData, storeData); bool isExists = System.IO.File.Exists(_store.StoreDirectory + "/" + key + ".json"); diff --git a/HandsetDetectionAPIKit4/benchmarkData.txt b/HandsetDetectionAPIKit4/benchmarkData.txt index d47d3307..97138d5a 100644 --- a/HandsetDetectionAPIKit4/benchmarkData.txt +++ b/HandsetDetectionAPIKit4/benchmarkData.txt @@ -1,5 +1,3 @@ -Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36| -Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36| Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; GTB7.1; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; InfoPath.2; .NET CLR 3.5.30729; .NET4.0C; .NET CLR 3.0.30729; AskTbFWV5/5.12.2.16749; 978803803)| WordPress/3.1; http://www.rimplaybook.biz| Opera/9.80 (X11; Linux zvav; U; en) Presto/2.8.119 Version/10.54| @@ -1063,4 +1061,4 @@ SAMSUNG-SGH-i900Orange/RTIC1 (compatible; MSIE 6.0; Windows CE; IEMobile 7.11)|h Mozilla/5.0 (Linux; U; Android 2.2; en-gb; HTC_DesireHD-orange-LS Build/FRF91)|http://www.htcmms.com.tw/Android/Common/Bravo/HTC_Desire_A8181.xml Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_5 like Mac OS X; en_US) AppleWebKit (KHTML, like Gecko) Mobile [FBAN/FBForIPhone;FBAV/4.0.2;FBBV/4020.0;FBDV/iPhone3,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/4.3.5;FBSS/2; FBCR/OrangeUK;FBID/phone;FBLC/en_US;FBSF/2.0]| Mozilla/5.0 (Linux; U; Android 2.1-update1; cs-cz; SonyEricssonX10i Build/2.1.B.0.1) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17|http://wap.sonyericsson.com/UAprof/X10iR201.xml -NokiaC2-00/2.0 (03.42) Profile/MIDP-2.1 Configuration/CLDC-1.1| +NokiaC2-00/2.0 (03.42) Profile/MIDP-2.1 Configuration/CLDC-1.1| \ No newline at end of file diff --git a/HandsetDetectionAPIKit4/packages.config b/HandsetDetectionAPIKit4/packages.config new file mode 100644 index 00000000..491516cf --- /dev/null +++ b/HandsetDetectionAPIKit4/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/packages/fastJSON.2.1.14.0/fastJSON.2.1.14.0.nupkg b/packages/fastJSON.2.1.14.0/fastJSON.2.1.14.0.nupkg new file mode 100644 index 0000000000000000000000000000000000000000..f6a29763fe52d867cca3a5676c7b37434971145a GIT binary patch literal 61565 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 literal 0 HcmV?d00001 diff --git a/packages/fastJSON.2.1.14.0/lib/history.txt b/packages/fastJSON.2.1.14.0/lib/history.txt new file mode 100644 index 00000000..d763750b --- /dev/null +++ b/packages/fastJSON.2.1.14.0/lib/history.txt @@ -0,0 +1,330 @@ +2.1.14 +- dynamic object processing enhancements (thanks to Justin Dearing) + +2.1.13 +- code speedups (thanks to wmjordan) + +2.1.12 +- support for multidimensional arrays (thanks to wmjordan) + +2.1.11 +- bug fix public static properties + +2.1.10 +- bug fix byte[] keys with Dictionary (thanks to Stanislav Lukeš) + +2.1.9 +- JSONParameters.SerializeNullValues = false handles Dictionary and NameValueCollection correctly + +2.1.8 +- bug fix serializing static fields and properties +- skip indexer properties on objects (thanks to scymen) +- JSONParameters.SerializeToLowerCaseNames also handles Dictionary and NameValueCollection + +2.1.7 +- strict ISO date format compliance with a T in the output (IE, firefox javascript engines complained) +- added JSONParameters.SerializeToLowerCaseNames for javascript interop +- JSONParameters.IgnoreCaseOnDeserialize is depricated and not needed anymore +- added tests for lowercase output +- internal code cleanup + +2.1.6 +- fix for release build in net4 (thanks to Craig Minihan) +- support for ExpandoObject serialize in net4 (thanks to Craig Minihan) +- added JSONParameters.SerializerMaxDepth to control the max depth to go down to +- added JSONParameters.InlineCircularReferences to disable the $i feature and inline already seen objects +- JSONParameters.UseExtensions = false disables circular references also + +2.1.5 +- added direct nullable convert ToObject i.e. int? long? etc. (thanks to goroth) +- bug fix deserialize private set and no set properties +- added ReadonlyTest() test for the above + +2.1.4 +- bug fix deserializing a struct property in a class + +2.1.3 +- added support for DateTime milliseconds +- added TestMilliseconds() test + +2.1.2 +- bug fix circular references + +2.1.1 +- bug fix obj.List> and obj.List +- added code intellisense help for methods +- added ClearReflectionCache() to reset all internal structures + +2.1.0 +- *breaking change* : removed the JSON.Instance singleton +- moved all the state from JSON to the Reflection singleton +- all of the JSON interface is now static +- added JSONParameters overloads for ToObject() +- support for circular referenced object structures +- added circular test +- fixed the .net35 project file to compile correctly + +2.0.28.1 +- added ParametricConstructorOverride parameter to control non default constructors +- fixed failing StructTest when run with others +- added create object performance test + +2.0.28 +- removed ToCharArray in the parser for less memory usage (Thanks to Simon Hewitt) +- fixed create enum from value and string +- replaced safedictionary with dictionary for some of the internals so no locks on read +- added custom ignore attributes (Thanks to Jared Thirsk) +- using IsDefined instead of GetCustomAttributes (Thanks to Andrew Rissing) +- moved all the reflection code out of JSON.cs +- now you can deserialize non default constructor classes (Thanks to Anton Afanasyev) + +2.0.27 +- added UseValuesOfEnums parameter to control enum output +- fixed working with const properties and fields (i.e ignored) + +2.0.26 +- bug fix objects in array dynamic types e.g. [1,2,{"prop":90}] +- added support for special collections : StringDictionary, NameValueCollection + +2.0.25 +- bug fix dynamic json and root arrays e.g. [1,2,3,4] + +2.0.24 +- access inner property in arrays in dynamic types e.g. d.arr[1].a (Thanks to Greg Ryjikh) +- add JSONParameters.KVStyleStringDictionary to control string key dictionary output + +2.0.23 +- JSONParameters.IgnoreCaseOnDeserialize now works +- added ignore case test + +2.0.22 +- added .net 3.5 project +- now compiling to 'output' directory +- added signed assembly +- version numbers will stay at 2.0.0.0 for drop in compatibility +- file version will reflect the build number +- bug fix deserializing to dictionaries instead of dataset when type is not defined + +2.0.21 +- fixed edge case tailing '\' in formatter +- code cleanup formatter + +2.0.20 +- fixed hastable deserialize +- added test for hashtable +- added abstract class test +- changed list of getters to array ~3% performance gain +- removed unused code + +2.0.19 +- fix dynamic objects and lists +- fix deserialize Dictionary> and Dictionary +- added tests for dictionary with lists + +2.0.18 +- edge case empty array deserialize "[]" -> T[] +- code cleanup +- fixed serialize readonly properties + +2.0.17 +- added serialization of static fields and properties +- added dynamic object support and test + +2.0.16 +- bug fix formatter +- added test for formatter + +2.0.15 +- removed CUSTOMTYPE directives from code +- fix for writing enumerable object + +2.0.14 +- Optimizations done by Sean Cooper + - using Stopwatch instead of DateTime for timings + - myPropInfo using enum instead of boolean + - using switch instead of linked if statements + - parsing DateTime optimized + - StringBuilder using single char output instead of strings for \" chars etc + +2.0.13 +- bug fix comma edge cases with nulls +- unified DynamicMethod calls with SilverLight4 code +- test cases for silverlight + +2.0.12 +- bug fix nested generic types (thanks to Zambiorix) +- bug fix comma edge cases with nulls + +2.0.11 +- bug fix single char number json +- added UseEscapedUnicode parameter for controlling string output in \uxxxx for unicode/utf8 format +- bug fix null and generic ToObject<>() +- bug fix List<> of custom types + +2.0.10 +- added MonoDroid project + +2.0.9 +- added support for root level DataSet and DataTable deserialize (you have to do ToObject(...) ) +- added dataset tests + +2.0.8 +- bug fix big number conversions +- * breaking change Parse will return longs and doubles instead of longs and decimals +- ToObject on value types will auto convert the data (e.g ToObject() ) + +2.0.7 +- bug fix missing comma with single property and extension enabled + +2.0.6 +- singleton uses [ThreadStatic] for concurrency (thanks to Philip Jander) +- bug fix extra comma in the output when only 1 property in the object (thanks to Philip Jander) + +2.0.5 +- fixed number parsing for invariant format +- added a test for German locale number testing (,. problems) + +2.0.4 +- fixed null objects -> returns "null" +- added sealed keyword to classes +- bug fix SerializeNullValues=false and an extra comma at the end +- UseExtensions=false will disable global types also +- fixed parameters setting for Parse() + +2.0.3 +- readonly property checking on deserialize (thanks to Slava Pocheptsov) +- bug fix deserialize nested types with unit test (thanks to Slava Pocheptsov) +- fix the silverlight4 project build (silverlight5 is not supported) + +2.0.2 +- bug fix $types and arrays + +2.0.1 +- bug fix preserve internal objects when FillObject called +- changed ArrayList to List and consolidated silverlight code +- added more tests +- speed increase when using global types ($types) + +2.0.0 +- added unit tests +- deserialize root level arrays (int[] etc.) +- deserialize root level value types (int,long,decimal,string) +- deserialize ToObject< Dictionary > +- deserialize ToObject< List > +- * breaking change in Parse , numbers are returned as decimals and longs not strings + +1.9.9.1 +- bug fix reflection code + +1.9.9 +- bug fix char and string ToString +- refactored reflection code into Reflection class +- added support for top level struct object serialize/deserialize + +1.9.8.1 +- spelling mistake on JSONParameters +- bug fix Parameter initialization + +1.9.8 +- added DeepCopy(obj) and DeepCopy(obj) +- refactored code to JSONParameters and removed the JSON overloads +- added support to serialize anonymous types (deserialize is not possible at the moment) +- bug fix $types output with non object root + +1.9.7 +- removed indent logic from serializer +- added Beautify(json) method to JSON +- added locks on SafeDictionary +- added FillObject(obj,json) for filling an existing object + +1.9.6.1 +- bug fix SilverLight version to support GlobalTypes + +1.9.6 +- added a $types extension for global type definitions which reduce the size of the output json +- added UsingGlobalTypes config for controling the above (default = true) +- bug fix datatable commas between arrays and table definitions (less lint complaining) +- string key dictionaries are serialized optimally now (not K V format) + +1.9.5 +- bug fix datatable schema serialize & deserialize + +1.9.4 +- ShowReadOnlyProperties added for exporting readonly properties (default = false) +- if datetime value ends in "Z" then automatic UTC time calculated +- if using UTC datetime the output end in a "Z" (standards compliant) + +1.9.3 +- UTC datetime handling via UseUTCDateTime = true property +- added support for enum as key in dictionary + +1.9.2 +- fixed to fullname instaed of name when searching for types in property cache (namespace1.myclass , namespace2.myclass are now different) + +1.9.1 +- fixed SerializeNullValues = false bug + +1.9 +- added support for public field serialize and deserialize + +1.8 +- SilverLight4 support merged into source +- RegisterCustomType() for custom serializer + +1.7.7 +- datatable support +- indented output +- bug fix + +1.7.6 +- xmlignore on properties handled +- date output fix -> 0000 format +- special case optimized dictionary output {"prop":"value",...} insteadof [{"k":"prop","v":"value"},...] +- override serialize nulls to output + +1.7.5 +- serialize without extensions +- added overloaded methods +- deserialize without extensions + +1.7 +- bug fix dictionary deserialize +- special case List +- int, long parse 4x faster +- unicode string optimize +- changetype optimize +- dictionary optimize +- deserialize embeded class e.g. Sales.Customer +- safedictionary check before add +- handles object ReturnEntity = new object[] { object1, object2 } +- handles object ReturnEntity = Guid, Dataset, valuetype + +1.6 +- guid 2x faster +- dataset 40% smaller +- dataset deserialize 35% faster +- dataset serialize 11% faster +- single dimension valuetype arrays supported + +1.5 +- 53% speed boost deserializer without dataset +- 21% speed boost deserializer with dataset +- Enum parse fix + +1.4 +- ~3% speed boost to serializer +- 50% speed boost to deserializer +- 46% speed boost to dataset serializer +- 26% speed boost to dataset deserializer + +1.3 +- removed unused code 786 lines now +- property comma fix + +1.2 +- culture info +- system.dbnull -> null +- skips readonly properties + +1.1 +- 26% performance boost on dataset \ No newline at end of file diff --git a/packages/fastJSON.2.1.14.0/lib/net20/fastjson.dll b/packages/fastJSON.2.1.14.0/lib/net20/fastjson.dll new file mode 100644 index 0000000000000000000000000000000000000000..f8443377bcc869b6948e2d2f28fb3137bd18f907 GIT binary patch literal 38912 zcmeIb3z%F*wJ%=#(R=USJ=2-)o=1jEG95@_Gu<;}@_$s#R61R;^lV)vBu9ozAna6owGO#OKHnA@0SK{^m3MV6YFx;l}&I z;-28+6YtfQKR&U0do~{*$a&jx=^gQ&bbr5Bh;PZnbA$cyY=69cWmkNM*PCgntaK+S z(yKazSgsjjUsram-`k5qpBU0YLR<-qC9xB}f@d6`2k;^8;&|wiZ={%idJ3U2{)Q7Y zjBEZSLR9hprKifu%Hr^sg*b!K4+yb~1Tp&WMIkDHyWvhD8b+6WP(Ch%Q&#REzqBmh zQpoHoAV28}0F?1qF`n|jxDe;IaV|8I@WGZEPwg=)}QU&IB>?omABpfRQB&z{buYrnOD#J{>xV=}1tSR4Xd-Q8dm*4qNJd&8Z{-z0f0wQpmwj?9^Ud*TIRU$jZsM}Db z8MRYiZvyABsn86l3I31d!zgxZL%KHxi3;6=y113KF|#d(;$XzQCKiYU8jqj8ur6jL zXIYVe7a@WusaroeriwRCuRT^tGRRGh+L#rwnjeY;Vs^xCoISM~Fx9e?(x+YuhT1*> zfZW*|I>53Ri_Z`~GbMJ9#L|Rff<+@f$#k(h%Zm~}mJN172~@I@>q@u{3RkRNHiTj= z*(z@3Fya9zuVge5NW?(6Iaq8;BaWF7)0y|mdq<8~UNwrFT5`~ofqf+DCS$5DHh??& z(^;^?&{k7#tR99Hn|i(mErwwgNY+vkO-(spx-slhM&Cn^Jt#GY;Q)#Vn4ZZ*X#U1w z{{BFHKxn#=urX%U4x%t;{RAe9P)vGt=&<&*uL2>b+{$4d)o3yOT;GG_-OA*u zsFA2gs=`hMt;Up`@Vb!Ic)UznQ9W@S%B85R+=q&UsAL?KfM3js-vIQ+1JV5X=fhFs zy;=xsoHqf8Us<`6if#2hEUY~NFfN7bVXECJ5-+6i8N+KYhGmxCh57<7);S~zA@NL&o*PQg`QK5L5x;wP8fqz=@~Z$Tj@F0 z7@S7WDr0auJ;CA(JX7OU#|4Z+OT-}yZz2IUXmAJpkStRo0cluGN)0gAX7j1W;25eg z-SCd5W*EMknxZn0fm?gyVG>DVGSbr_j{;SviKn4+(;^acN=Wp~Jr*dDfU*%1vXV$j zBw!ST#3YU*85by#Ky^Yw-DOQmBmf8rJ(WmGBmfAB!AK+}63|LQLTx0H5(y02YD#PY zR71)jnQ~wcm_bOwNWj{xrg2kE@deTivK7{_#ywJtYhA;ef}vL=GmZxpb_*m8SOVIc zdoX^pIcV5k0wt+MRw}GoD|1lQpv7jYMz_5aQBBoOK>SuRtlQ=JI@j@_C2sRI&qtg= zbf;AYQ&v!#fg(LD8EcX{UMDX2sDO=1d#AVr_Hm3cK<8kyxgd|>_EV1L3q@d}GRvm>)Q%z1In-h+KmpeXO`5 z!n3&NTntc7WmI@D7+5~07B0X_z?)c2UsD`H8%!9ukvIu;4wB`u2gHm^gXYTjtIE(H zv$7k$*Ns}^ifnBH7U|0Vh(}X=3u^+Lcf@cNMfe{x<)ATa z)&-KBmhb0eE-DhRV>cAla%ye%+w4ej+RlK&L#qO)Xu@I zk0C-Pz*FJdWbe*)DiJp*|rbOq!%cVD-PME!NkmD2Mm+F+|N;#F!rxl|p?~3FUr5`NpqnvA@GYRH4}&HHExp{2HzVN)f5W z@&G+H4J>HONDkvvUOv3jfva2ZoqwB<5nyuqttw0e0tC0YVjF+HOT{Wx4!!sSI;FR?oc# zA{-Go-uWbY?1il4YV1hMkgA!O*z|Jfm3FOHWMg)1%xSwHIux-Y&LnRq6 z-Bj5R5IAzIiny~dX(HnChNStTqiscY#sOqR2Pv%PX2g}T))+z{BJdFrH`P`yvt-0& zQN}`%&|!E86~tHDezTBVfx1W0@m!V2Kb{Yrl1V9E&UeM_M_wD^&)?}d=yz=Bt_T>bR>`&Z>(ig9&wd&$32T#X>n?_XI7dHQwe|Np$Wn$8A3i!nh9k1?h* zc}&}b-g+cPZgmjbZvZlN#!-?+$yq3Qza0X#D&HX#^Ti#)mCw8XaIaJNxW9fI;_Kia zOR&#>nNHB0R3rzaPRPB^QS6R#TRB@30~kWH&!$rJ5YWnh=Ele>sgYG0mChGc?4$o! z#Z){}CoZ~1>ev?*JEIovvNgLDtH!1V#C5P{_#%Jos#y*65i{zBYAf27poZaiXCn(g zirBzRO%683r!5J__d#$c%?maj-!ePcxUprXRWqOB2ghv-;}L8Owj3X9bX&#;8!KDJ zQneUW3!~Z}&=S>thlf?u5|d0DmSb)3Hlm{`HExi$ca6af9atRr=moBiSJ!QLPQnMJ z$G5ZtZfrR%xj{)8hlonbZ68M+g{?1Qlkol~hLCG4p)wNHxUoE<56Vn(sT%Th)oyaJ zokRqAr;-FV5vS=a?YokY7Imd4!6#NY_PnprQC>|;tt>OJ86Y|P!jq42Re ztk(|Ha)mXKmT7$t!hLLgk)>s%iOyFyVYH|c0Smss1Q};u+-sb z@EkDUT89x9NVo1`OXym|aK?O;2!E>%4JrPK!H0sRKrBLMfk0t%L!-8urs;dJdo~#d zo^+8%J#ZS~a}TT9)tfCoA#2jhPKe}gTw%5{xx;X@l9iT9>oDeDEjP9y#bC(shmoa$ z_}DyZT6zNE0P&JvgJ%K@lGU`B`O44YVkl;^>13lkcY0ZQbz%-RnXM|QYCt5l*VP6Q@_{h`&=Uxq%22^=TOm}i`{ z8_XKV5xQY|y_9X?tXH5k^JIz@cw%ZJdhK~@YY~wrXQDFMZ-vv?Jl(8wljEGmQg*dF$8WU^|49=PKO}OncNy1$2FRX05)wsU`m*^s$eoxan$j zpp5Ve3Un?=51&9uz6-$Fa-1shxql~kL5vhR%%ho1s-_zji!fw)Y2;H)_TX~Nv9|@8 z=30wxRlsR&0>g7FgSS(|CVRwVif*WhK_3CJ3i81z4SX2&ONVSwHZxUi$}`9cmXPUv zuySF!q1MXKWM&VU%kV^ivgr-kG_z)EoOu`%tyB}IZ#?bQiIp@FT#BIWs8Ym^7RCz; z(o!dysamU~>(hg}Z6+2{1)rE%Ew#lSg!zt3t$*JJTu?F;rnG<=ISge`TvY0If#@XW zN+u}nWguj*8@1Ua%@%Ho{XMwES!O`oi1~vjh~yzX?2SEmUmWNpJ%qN~k))H^aUq)* zJueGHh0UuQrz;(nNvd9VxL$QBbd&?D2>KO*$F5LmIYI9{kVSV0&fVsZ;zZwkuNH34 zKhcNM%RPBmT=cQh8U3^1oBqthR6(6N8@DHs$?|5Q$vjLMSyCZO4iW|h&}CI%8+=;X zWO{w*J{8nWBY_PkX83TZSP6%NTq|)pN)8fU9u%7-T`Lu3{gYKp(r!$!nZTJ2LJ1rZ z8I+rkT$OGfc8?~y3`GYC-(;AH9pEC-5730Mk&lH1Djy4`-DbVE$?!a+;LxFKaunVG zHJD;}lklv)k>~Xav^x&-s%!((YPl+nKCA+~rxr5!!I3fMe7-u-slaMPHsSd5Tdm89 zuC{7#loMN-4CxMX3DTrWJLp}2o~QVSIp2Dp!<^FjN|WfkQ0}Qo2NSUGaie&x4pmp+ z_#J(OthyU3_^x2wtXDCr@==hTRT`{Yw8O#)U)$$VC2A+IHbIYd=+#+B*~};o5KRtB zeXT6dRy%TNu|RT@BOTWSYQ6!@*{mFgJy&(&42&7IPVrllC}9I5>e|(`Go)%&et{!- z2n4b13y?o|!R89Z1hSowMs7M9;6Py~I7!u4BZ!BhnU=Jq zsODV={1hAYW|h@D6Tt){Ad8^uH7*O6Ssk}H2 zV2QFq_u zSwBZUTDb=?lR4|hR2G``5FXXBFtE^KGZu+NI^cWh7KK&?k-}#-KArerfe;vmxDKC( z@zG$llklPa!`b*y{%PRfz{f+n?J|H!sLUnD!fgwsQA#N#}}!AD{rW*P{09Z>vgVVu}JDFj>=- z_8o4!9#woYA13jK+YYE!m1t#hBmiXp2qc`c1>}Zf(qF~&$%;|s9 z!$YC|*oJ{S0`b!D7)K@y-0Q%xRw;fJIbMrU{1}RXT8G|KGm#((G^ZjV>0nMEYR8fT zq(Q`KB|)QZY7|7`Od>NCt%-xwhkRa46wyTBfe;Bs!lzgq-^9Ynic*)`@oO{_GFR#KF~*eM23n}BzQAgVM3NV%uuHttfSt3 zl%N7}#4b)RX9wKKc&1Xcoa*~;+0O*(2Mqpa`#JDG-H$0Q#dr|nV+CTDVE*p6oEPm@w7zI>Ueslpa+)4buze% zLT}{pJAxc33rAp`VX@O*cM*7ugGbui)K(-egF zlzqdW8@0zJmO#Tox-o7nrz&(~f=uCUgvO9eBG51z!zvv>I-=5Q``=j8I@V~6@gA+Q zWjbgyR@XDRm~BX&>Nd#Iv!?5~>Dhzfn|olCxNNqXBesLrqj2_YMeO`##A+F$F8?uL zVouaae4Ix?aib-mgA_YP0)}@GXx?nmRxyK@2rdVr!bz=j=PGLs9{ZYdd%+rKfE-1eyA6Z~uj#1sxJ+LA?yKv(CZ zwD}+u62^%YuejTg`Z!kXy3)7JfT+;;L}~=@6nVN7qy|z>06}Vif>dc!R@;LZY}8`2 z!hO12#m#D*BpGZ*(sLfCtE?JjDgN9ONX=IvXq(>zPEbpQR1RU~nZ?#LF)B7y6NBPn zJ1py3s?-%%wo#9rJ4dIICqFv1NYP|;YDu3uT}G$YNGB%cln_t7TawdHFzm^r=J?oh z!gd4!RvR1`$%&?&g-{tRZ8UKmSlVggok3GdtwxWSN??ew;VCTaTtYyq5FgwZD+Z2| zEGh<$IZ{%G*%uT?TCNekk4lK^?=Ov&f}1HAYyJ~x=~}hkm3Ug-Re%QH1#>V4Wrosg zsj)UY#{AVNuD}iMHF&l?fYB=*HxFYC(s{2c2UVbar4`(Rr|Dgb>bS5AgclC1Td|yNa@gcO!7~ zJcvuFyp!Av|3k|N9hb7g%X>EpP@5O|C|JFWS(~Q<#VZOaB*oxxGCVd_)gu<+fXU@0 zR$-Pwp4X5YV6x5#RrEfEs_bW^PTE>uUgNcd?(TnsdHN9M$@FeQHPgEpF#l-)2}5St zOAW!~?udHfVLoQ9LcXj}TIgD$3R457)xiQL^S^(-iH4-zkN_)#?Bp-UST)#9#H{r` zg9es&D`2c5IXhaBxQ&u9qe$RJ)i^w$6~W&QQ6(HoecGis^kG5OEd9c$3A)zUtrIzblq3lDeRatyfo5)diKEkU;Y1&}$G`PPgw-#bt*IrI;07i2LLY@}aA3$oyu)_>XVrhP{loeiT? z2Oa+fqniWHl+o3DUqS|lU=hobMkfy_n#t%!oK9Hk4B{@)*C6Hi5%q#H{J*K!48t{+ zPKzfY(}d$~Y(UsfDaOMJAWkHi(+PsBCpMu>PizFN4A!+&1jkLUlE~z1@`*#W1hyUs z#S-V>aa_x|9A3A=>jALtqh1e?eN|X6uscCNc{`t_EkU2Ku}J>Qqx%fm_41`~mn;h( zxLtvx8)hr{OP>R9NMrE6LNtHCG~t>>5;P_6uGIm9r^`k$A0Jo?KPgS0AU;GH)=Z5= z8$D0c6F9r~hlf#i%iLP|Ai>n}Rv1N;sV&b`H|4(izEX%ywZ--5FU9<^g!j<=)OugV z0BYQ}jVRRj(DdLQp5%xZ@bM-FrC@#F3egx|)nAPZtpz$a<@Y(7>trKb(^FMz1A^DP zP`OFgIl2(jN^cZV-yDrM*|^lJ!8PG8VIq=9-3GVq@nTMrVApgiVZlJ-2NJJ=^Bpmc zfIp4^kAu8jVsNo3;b*<*=N1=2$f42*d$2>*XlK0;5s& z5=9HRg-cMH*5DJ88>L6bNhOjUOKQx?yes~GO9Dzew$Q^vWB3fhBno7FL#p zx@HR{>*O_CC>h2^^gQfDd7G6+5)@=z`jg`|Ul!Ops8GyB-2&R4ODA`XB<(hT>!1(BHiqx2v1)bPB z_aFx0G#MKsPl6)DB>97`@w9IR} z4LPT=|I}&xES&mnE>Yio3Lvu=1vZ{-LrBy%)isT6s&5+C)X+4(={R`uqG*)&IBwo* z)H_NJjp_Ng7#M+9PNcDKK3>8YQKEcFV}5>MREcsajhXqcgQbyPq%n95cIxMSpDK=? z{l?sU=^}}J$+^$Y;QT8`weZ==OdnD`)=R%N;aD9`>pr@-!RhnLk$zWw(-Y-rzn{M8 zk&*p0x=pz}bj;VK4U;Qbn}VZXcWlY0VLbcb$Z+kB?><|ao!AFZoPwuSH>9e- z@*V`Y*X~Yk!cKIJrGo!J= zdjyG)&2M-n&%?!!b0ap9j{=FWf=unw9q)%oJKm1~1Bom~j^iQ2Nq9&NuK?Ak!3U`+ zCu-CU!+`*S;tQyFC34toQd7PJ3VJ_Avh*tE71?Q55DWhTEWKJ43)aTmtehdIF>l3AhmWU*h31i{Kj z^*t;l%lirFL-;gji{Z0pLWWWCUQHOP+ZYKMrR)2aO5n>2{wg)Rrn77iyzd+zk0XfITkM zW^pHOIl-Dz{f1E6D^Mw;{BE_eBGh)6k&fSLy3-g6wZWu7ISq-V@NGAP4^xMiV`7cN z(0g^HU{46O;hac}5AiE*22WV-Zny~#frFcxi^KRWmGN0u6`HV6-`mwGnM`fqfon9%3@&?BO+dT21#WI$#I(?Zq0Y4>{*mpdI6e2M$u)UulNAE58KIatW1IWu#yPx~*_^=G^xWM+F zR_*8vY7R80O|>JJOzobbcK9a5UJNW|KX)AK9LX!SDfcMm+NjPyiyXdm^9wvGoV~xq z!`S;PK<_yM&jUDnU!dfR0QTW1EQ-y*dkOghW#P)WKg;_yP^?Z&ymaX%d%^h;^+ImL z@P0!n92D(+841`q)Efcq-rwS3c)ydGSMlI(QSe%ML6M)}Kjz0D{PXdcmHQVOGvCS^ z9?d}FU#TZ6k8r@<9kH7hG+^S?Up<6HpE&Z1p?P%Q(S`gh$aw7KF<@{YYt@xTiEZtz z5%bnjW4HAD8=&rsSZ8&eeJhAMI!mF_+53A`;DI`O|A3^<0&w>JTM1243bK%#y?^x4 z20L3On2I@j-vnNvNPx+Rq*jJ<_Wp_M{29>MTNJOu()D{S3OBiK1ZShWWh?zheUy!? zNY_4GHByNvOTOC@v{RoA`5N9^U{SvPC}kb8YwZ!T4%`|EjFz>{+Kk1J^sG{e`euka zC`FA^%aW{vWwH*IWF3?mX|k|`<--0Uh$>+Rm9QBlg)PY$y!P_^1^5014XkSKZ9IY{ zX$Q-s-S#+`v%G&tjpp14-sEKdmAWMQ|20P50fizX#VJX4jp(s#e*f1->ivxwEzYy^ ze)AjQt^uqPvX(M#g;Q#VV5SVvX2jlCg}Mb z*7JAKq15wZ%7UC_xilh(o{x4X%{~9CzNAb=mFluQ2Bb?U)8^zRrKZUdPGOXqI(y4h zEs6Dn>9b;#lZV%k{=8^EBi5K>%Z=WX_#xyr7jmPxdZSw7{tgN9n(9Z!`S*aSuw&uc z*qFAjL(?MR$e0_k`aB9eqL;ac$Rl`1kZZQgSszC(kXnSZmw<<}8#h*!tjC)kc+m(8 z6n+Y%*3*$p1?q4(6GVZ5T=VldtH%2u2q@G=MZ|3GFoGOJ^PNYVgR|@!L^ygBZ)Oc+ zK{um#gOLL3;hAL_j%|k#E8yb7GeJ5s1_ADv$e2j@itN0Fbou3n+qmF}MQUTww%ch; zkx2B$STK-kM*yxEk0pG;zuAN!NdRs z3wZe}HQT|Bi5x>^q(Y9N5>-os@N;FOsFb6KVieIxG!nrmR$&y5hs`+cdU)C_5AiMn zcKMy!bHtR3<(;Q4>a-7?CeQlu^8L3+TALsnm<{hoSKvv1|DWzhn|AAYOcZ|O1U&gK zpXYB`|!9@`^jiO|JdyfuWA$l)b(kMY4B+n z{Ee6eB^vI?aYR7mdE1i1P{1BZF#D3513hH0JpYF zm@u#^;7(Ywc3C@~)yUsciTuJo`oaMJ>0sf^O}7Sv*ffg2O`c9)exTmB;}gTD2cLh! z=R5dRqhJD_A$+LL0({V(ey@Xn>WTD$@TU4$Di1AVJS9P0WEQ*POZKO7#5G~59(p@5}+l{GtM;dJ`Tg%45IL|K{elG_^wIm zE8V@WCGKDtufW&o#j_QJ`6I*1N=i>*xPakV46muYu+kD=W%xwp{godUuRwB^s1Cmc z{0xRm9iqP{d<1WOT@U%8ewcW81sIHd3_+XW7=|?r$1yyfVH3kvh9@(e!*C(PWeis_ zJd@$jnBFm#xQWw`0J`E|$B=xCDw0DT!w*$azl#9F;>jwK)t?!LBb4p{v_yZTHv-N9 z!{R!|-^KXvMX2qMB1G+l2#w|U3BRuwhcFr{F)Yv~6CEo5u zO-uZk>-;VH9O}=H5#~UQdc2ZhpqenrYMP4$43}5aENo+Vh~dn*Ty-M z%Av+fkPG7bt`j)7TIG&sDx0`wrI;f2qg@~88tI-J_I3g1;WZCDq>jKofwQCn<%>N2<|pE*fff>?Nbr3oM$J5W&Is+-M)Zxs=jWY z%dm#wM20O4=P+Eza4Ex;4A(I{n_(JIO3V^lod|f_;oPbF^b5{ipudaZQij6}zo-+w zQ6qRIr$55@k21WP;mr*1W|-zW|IF!^IQ=-oA28-IKubL3JPr6X!(T9b#rY*LZxBD? z&&~^gG_#g?*QEL)NKy?lj4&L}FbUWyW&~e`tX2nq54a)tHehe?2;c?5Ae8jO!D_%O zg2w~i6l^vOacA%p!25#>jESNm^h>~+(DQttD8!{>w`$dp|1)tY9)85{a&0VfZ>ijk zS|e76`Nvb)Rb%G{=W3={&bb3`f_|GmI-mRQ#%0=4z3P ziB&B!H{IyODf(%xGB?k-9xu*pRJl&$CU~NYRBoqnE4~r%uF73*d;#AsI!r+Y`n%lt z3ckN{<#d_58)XgR+!-?Wpm8tWpFXH^PasFDGp)xoE8nGekvaE>_MEYlZvm<75$%Za z5P$bc=0fIU@Dj47Y{!D;n$H{hvT)=q7e zxLD=3q2_8a6&pmNGJsr{C?G5s;(++DHLR@_k1djApRlgfHi#J%3Zmu>)~B?y#7!#q z8S8V}*k+L-d`IODTaRhI;^M`!-3!)}T1Hea zk-68A%ZkG)_jl_RZHM^lQdw4K|4q9kJn&4a5X%|muK%BFV7 z-0k*y^b8n#+QmY@_cs|bJXsuBih|nEPKwF zr+=-OJ7WCQDCMZ#Jz~W+DyIHkHNGKs6m!+$o8q9%iHV`#8{ZU%WzK01y$v5-wVm5J zr-c57T(`>24{7GN#kDdgmLd1gsHTbaA=+b|4XBAU!)*+Al)(!)eMuSSdQRWK@J5EW zFubD--dUFZDyJnzQvL=oy10+=<>?0)^T<(fgH0St_+xJS1lM_{2zBus(uSZ?P5hSO zf4(MhrHj#H_c7hvdkG$mFURQO_uM~U0qk%}1 z_PKIiBv+;0HKytJ(u{4q#*);w@&z z5E4^9BUBT+B8IZZHNKriYwLpyf5h+!hR-s5iQ#L2)#f{Z$C*Km zJYNK`8WA|bR4`pN`NRN0}bL=;nu(`?aeUt^-g$Z;BM_>V^#(3 z&@KSg2iF?Mh0tVeJfX|HC9{7>=nQ%Vvgm!;;p1wew5*iBBYh$Xq^(Qo< zwhTSy1J7ztqV!qq$AB}~YrmwORCRk`wK%2fi-DK4v#Y)u*dWfUx({%7)!W8u^!Pob z4+=kVy#;$ifd7Qd@{Ht-JfGY3BYg@C5lN4j-QPee8avSKFE zS+ODV=Ria!d8Wmskug?Qyrxsz&qq$QPSj5con%!rhlsZ!v1(o`h@Wn~RY;lN8(C$w zg2KI`UCEZ#p$e|qt{}C&fX6-rxZhe1c&pV7$xjSyWSMVd`PXaz5&5k}@_*f0%`|(N zW-s%95vLD{717o}S|^%^#MUUrq7O#5+ZT(AqxrPU%Uw#4d! zSuqr=7I(1pvf@**24L=p-7DsB{h0y zNPm_oYx*;>w-E!87F{e}j`asW%M$($OZYo1nTen|988PXnS!Jv^@?~%i+=|X_1Z(x zdxL#~;*X1&^2JQERn%6$3j3W{{U5=!_O-wS_d)P~vimUCd5qyx41dM&WrlAse2d`> zhVLp!8aM-#HS=ADGkA1w@m##cm^V262B%-<^iACMkl0Xtt$T+UtiBoWqt%-NFX^AH z?$&SOnuo-ft3T_0MtlqS&xjvXw+3Eje7#0eJtTe#%pvg`hJOZpm?<9;M?m3WuK5^a z9^>>=oPG@>{fqmWetOLj_Z@wEO(1kgcr`ERhs4Kf+|Zl)p_*9e9sSe5Q+j;pHT_F9 zlR{51g*Wv_Yf>nEN|nw)`Z<+84e3{qenNc&5{t==?YNTs`Uf^S1uK`RL5l) zWq2IJNr2Sj?$8}#X6?18vyd@M@Eyq$jk9Z8A(`#9n*#6XyH(B4qs{@O?+}-v{;zm+ z4eYV+5Z9xAFYC-C_{NE7dt2>aLX+4lHb4Vk2sCJ9zrW&fwHl=VDUHs5X0Yc^X>1r{{c&>I$#SD#Rd6w}TPLns7p^>G}&`7&xXs_0uk2<6S3qY+Jr#PR*`b{$`syU3V&n@ zZ!v|xGKF`Ug3yS9sSyQ7BMKE7QK-`H0j$=(4LDZ2AFx4t2r#bw5O9+AIAB71QvZ;+ z&DpKD;QO{0RJ7o&>bn8Y7B2#h6CVaVRXhOLC7uS1ah)^7Pb$*->-xJ^kAA9ia)pDF zts@oBn{xtt1D6GE2|OBjCGbw5)*5e}Y;Cf3TK{A{XgzEF*=n_C+o#zp?X&F*>`U$2 z?8od^>~YR2r^mU-x!U=*^Q7|&=XZ_>o)Wwy_(1T5;2XiWgPI$1$GElb6!#?eGWQDi z%kHn;*W5q2>p}-YcZYrudMfm8=*)_Z73qp?6=M)v#IXJ&VhMfQ!0%9mf{0$aLY1bD zvt>FHzZfTSy0`>qZyNU6ws_tAlNkuq2L=M44E!{(&brRJ)A}}k>}aXI-cH-Q?d$F5 z>`J`ne@<{~aA$C?+u?S)>)dnQ9qxthKKF6=DfgG|Z$rNi&97KiVeX^YgKmo`#t~wo zIT?_+@&7dOHYZ2oaDR=zk+=srI}(RC;P4m1Xn|co7SrCg5ON%+3UhiOE<}|T2oiCi;wQ@yEZ(pBiPZ!epOrfi1duB(v zSR@vExgF_3A(InSvn!L!ru(wHku4@gdnWIrxzegM{tcQ8n&devdQ0V?lK1*i0WCzg zcYdZ{EXfe{yx1|cD(4L>>)+~i4-I6>vSLkUYhR|PkoBl?Kf3Da;x>LxQV@%BnRFqu za?5$BE4tEKGwoS!l+F#EJ5B7!_jtL!>=w~AlrLm<2vx6hu&zwPEjAsI zaGx#R^bgO-+s%c8*}h)LV8OsZroUHJTb0AOAcicOZ1x5V1A};O$!zuTQ{48k| z+Wu@0{yiYE$m`#k$rZXinq6^bE?daF?^wGAGCgwkdwGmpu_O%Hdc`_5!V+7upsQUz z7Y*hM_?;Z?ieFBWFDW&2gN4pKdCur{ArIZ(*%fNA%VJW8GbCDaSgP0{984EFW$^ydZ2*LE*L z8#z^7+r10dWYWDW`}^3SpX=^mzTf`I7g`b*6WBp~ z`wjSyTxO?O<9UUp>HKzS8jH54`?pEwxGYbK!1}!wo-Wrn1Txg)%B|dpydo#c=7a}R zmX~fD-a#hdKd=r!Z28XgfWj^7FJ!jCS;`vhG-Q&MQYQUbQkA5osakT;U}hvnDhfRN zQG6VYkj4P1rr9u*40x>}Ly`IOu&UulPWwFX`~}-lQ!Z^;$Yd9mNA|QlZZ&C~mMn6T zm4MVRuXI?YAULU zUOzNo5Hq%UB~~DnT-4{~GotH)!E`RuD+~OLEP{8#Ko@yC5F#j#qxk5~4Q9mRbRXK2 zPKdr9UIx|Lj2Q%{(6ogfzAhn0PCj0y%7lKbnIS?_LZpNRRyVbZtnEL)-@CA13>3tc zg6Jt}Cj1x0EZar|3euS@O82t|70dFA`qFv0={!@Hz9Fwxbd>`?@CG6aw~&T0V_D~Q z9dtJ@^KqLCL;bYmY=2e-Q+~mM+%{-Ve<4qm6@TQl zrL}ajBd4M=(?^b&T#(Oac5LYz@+X^ci*w$NMLbqoI3$gtu+-vR7Sk=xX8N!UA#hU0 znJF-e`~VATWLamXupPg5E9-&_S+|%~#VEl499Uu%%oKcDlCL5+n^&cK@sIbNFE*Fy zV0Uf^ZKcL-!$dFg2BE%`T1Js0sL8~FUa-Ms62C?Ca4y?Vf!hGZT!P#vDF;(4#RdY( z0pl*~G=twc*uqgyufLRHndvPEsqd^{JIQ!OnuCbmY!4BqSQoK2Nd)cEqQ_t6b8_u3 zU_QWcF>1#u=tnARFe(IBE#zGxY3SHatUGzJaU4!<6s>ari-2#T!jZHwVnIH*r=u0 zTGS4umqV-$g>()Rg5eINd$NTgaXzASUl+Tx1w;`3@?J#4WO{O01UX*+(S^{DUKsk( z1+=#2vfH*FqiCHJ%h7GHJZFw7REpn~LG%ueTUKRqJFE2rGyU7JC+YTR)so&_mM%wZBzP%XmOpblwi#WRxeO{wkI&mK zgvzvOg7K-qnQ~aA*?1_(Mlj3rKcTeea~NgQxM)=*8Ax*$4s z^}vye*|DfkD*i+Ecx1tWD7h5Z~3JL12by# z#3YyHrKQ6J{F4zj;=T+86)e9|Q9!pRTM$Fb@-m{w$}pJA9BmkjWC4ejWX~8!2O`uy zOe=@4M$2%!T3O|B<{NyAc~&QffpcHUY442ZTAuyIlfm83^WCx{H`g|Bm< zRRE`Z zWyI#G*l+DpN4P*CW&&z${}yl8<^}yjm|nC3MwYY+9845I6kDRM!q&cCA&2a<3N=(R zptB_AmJ<@m&Q!|1s{n7&!;>PJgoa2bfOb2xSb~@L68R+@qbr)!v}|X_+Z1eG@Jz%0 zrD~K^P?>r6b_y~{Q?Z(0;5leKGy*;nlJw1mA_P_6kEI|3EK8Vq@+UNDCCWG-x8wN! zYMh^Ode$5-CL!(}5(5IUG~P9xjd%8hP0!=;C6;0O)vRDY-e1SA7l-s)alhGzdKq8~ zA_qLBrsBO&`cDKH+A23@5^DC~`zbi_MmtFrueMe00qse+aiw1HHFx~@OBd?ofFbHx zv72*oz<#v%&`Upfq#6{P$C=tL)Z2lQ9mw|rKY$wBk@mz^KoKg9N<>oJAMr4t`aB=~ zVr0fn@VpT%3Fa8~GaLk5FYvmqCh%TE7Ce{e zSS>{dwIdodtA1~N;3&@2u$AIjAv#2Xo>Fdk(4~1mz#v4&8kGL$>c)AFj@6@>y9l&N zf2bE4u#&vw+L5oAH7AKc_H3Sr>Y#(f7CBbx!sG*Xm za}t`?bqkl{Q2_V z{&e9NuDj%!%bbhi!ui(jjqB=Xym*;q)kJHwux^EoxX>)2Yteeg6k0fJSkZdja%@x> zuZPvM!2!BKw{*M$twkHmxE3a$HE@0+!^sRQ2}VvNI6lDXW-G2mooK6k%mglsS2TzY zr8P?H=$E0SH;eIegD9b+Ci+>XwgpH z3SeO22Jnl45oicoRhl+Igq;xt%OnVuCVGMx^%p}rd^-w^Etk9xF|2HuJP;wB0qQw5`)4K7M1OB^L9 z%48&N5E;~rv`LH=Hym_IRM84lBPT)}TBJEFiK0j9K~}CV_7m+K?;~T3DROE&vp+9i7fF@kW|3D+u6wbHc>ef8vo} z>Yr=ZJ~np$v^`C4*L?Kh@3pUaxPM7(?vdCdg(nvN;TN0CJMU?ElmuB%+BM$bB(zOL z>rJ8QMuqLbi8xHmAZ0cc_Rv1aAjoF+o6M;toWo z!|Fgb9J5V0Mzp1RibMc03Py;GC>I2aBQp-_3)YS)ByN_ zu4YXnR(OSYe5Zr9k~5dVvp0SrjyK}zz6;Ys`8eLV=-Cd{mv-ma>=5BqY%NT) z(`mX`KjerTxRe|^){=mYe^^0kozp<}yniMv-N9URvd?B;39*ikp(?x*k2JD>E=FqA z&=YQ5hdsyaKy?2smLrT^l?cq?0<1)|rm&_#L#k}@cG3OIfaEz-dfhP2cGw@GaITUS z5rX!I8v=qH5T*^YWOFBxHsHnw!ZYkB*CHunEo+cdi3LasKHPxC$fu%+MP@{81M8Qp zp^$`{I1+^p;QMOqfI@>1mL>Z%~p3^k7l zhsEXC=x+Z^r=fzL%apvvLfhwJ_|yrF2P>}Zt+rS|dRmk(6h?!YlQC>SS|>jpZADl? z`VMW5!vJQ&5;jB~vV0=R(}@*QiIuVrCSZRDmS*)NbJZ~2@If@c&`8j)8Q(C?hU%g^ z19ZTo#y4PrSMESgx@_b(#e_xnZ<+uP*Ln;_6dSMtsW{<=NGfRa+JO}GHj;w4U=2ar zb_^#-24QPK2tSBF+YaEL14O8YAG0U-LMDT}>!2LIl-3R{vOfcT;pLQ{kc#iMmIh@3 z3?4SST=$n!A6=?hY%-QiX>7ozg%dH;_~_cm{;Wl=bN>#`uSUMn4k-;qIcl_xkFJic zrpH<+_-Ynwho&A_w@LUqd|9LoL4yqiC%*~#{^bMiKS`tn>VIb9FdMy;3TakoS5^_DW~{>y#q%Y0-FFx zTPNT&z_rD+2Iv+AsaRR@(;d!M9BuF`6$1b2St^gy{k}}T5GOP}2fRM=!~@&2J#o6r zkK?959tmQ{8`eZ{+SJym%>dZ$61izDtu3uHTCknRZ-r1S$q9-b@tYD9p>*rDXXera zxMnY&*W$1O$GO_RPq%3ME*^CtQGOeQGgo;8xQe;oJaSQ8)vkzoJsr}{dw4kL#mB@NmWF(4D@cHzW-1C`|FoWoQJ=H zbi9-wk)ksG!_9K8y|1qmhr06p#7u@?#iYU`lSO$#JfQyl)zwes=_MY5Mk(Gzh zk9^MKQf$ERBux2VJ2D!m(iziYb+EJy$3=8dM1PaGRX0lM5D70t;pv}CaRqUgc@csvhdf$RkMuVUzuD5tpBaEOLh7#){gG7Vc`2Rf^?_cRM=XjX^ZRMRsUe>{ zqiq}iHqmnQvyEGkqy{i*;&vOxTtJ;^=%*E*W|bmsY3Dvys(N&`NqzcbrW{H8gZq|a zT?HB*I2z;=$r9H`w*@)yOR^o=X0()!C8IWc+d{*4oJJozzF*s^Md?zn|C{{XB7YMr T&cAN(zX?zOkB$G|B=A1~$I^k# literal 0 HcmV?d00001 diff --git a/packages/fastJSON.2.1.14.0/lib/net35/fastjson.dll b/packages/fastJSON.2.1.14.0/lib/net35/fastjson.dll new file mode 100644 index 0000000000000000000000000000000000000000..f8443377bcc869b6948e2d2f28fb3137bd18f907 GIT binary patch literal 38912 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 T&cAN(zX?zOkB$G|B=A1~$I^k# literal 0 HcmV?d00001 diff --git a/packages/fastJSON.2.1.14.0/lib/readme.md b/packages/fastJSON.2.1.14.0/lib/readme.md new file mode 100644 index 00000000..0482bc52 --- /dev/null +++ b/packages/fastJSON.2.1.14.0/lib/readme.md @@ -0,0 +1,6 @@ +fastJSON +======== + +Smallest, fastest polymorphic JSON serializer + +see the article here : [http://www.codeproject.com/Articles/159450/fastJSON] (http://www.codeproject.com/Articles/159450/fastJSON) diff --git a/packages/repositories.config b/packages/repositories.config index 87b41fa7..73f1b354 100644 --- a/packages/repositories.config +++ b/packages/repositories.config @@ -1,4 +1,5 @@  + \ No newline at end of file From 95f3593aef452658bbf890063dcce5b5eacafc1e Mon Sep 17 00:00:00 2001 From: Info Offbeat Date: Fri, 12 Feb 2016 16:19:27 +0530 Subject: [PATCH 4/5] Minor Changes In Config --- HandsetDetectionAPI/hdCloudConfig.json | 16 ++++++++-------- HandsetDetectionAPI/hdUltimateConfig.json | 16 ++++++++-------- HandsetDetectionAPIKit4/hdCloudConfig.json | 16 ++++++++-------- HandsetDetectionAPIKit4/hdUltimateConfig.json | 16 ++++++++-------- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/HandsetDetectionAPI/hdCloudConfig.json b/HandsetDetectionAPI/hdCloudConfig.json index 672637b0..cee015e3 100644 --- a/HandsetDetectionAPI/hdCloudConfig.json +++ b/HandsetDetectionAPI/hdCloudConfig.json @@ -2,18 +2,18 @@ "username":"65ca2fe072", "secret":"RK4LzTcJHdq2C4cX", "site_id":"56163", - "use_local":false, + "use_local":"false", "filesdir":"", - "debug":false, + "debug":"false", "api_server":"api.handsetdetection.com", - "cache_requests":false, - "geoip":true, - "timeout":10, - "use_proxy":false, + "cache_requests":"false", + "geoip":"true", + "timeout":"10", + "use_proxy":"false", "proxy_server":"", "proxy_port":"", "proxy_user":"", "proxy_pass":"", - "retries":3, - "log_unknown":true + "retries":"3", + "log_unknown":"true" } \ No newline at end of file diff --git a/HandsetDetectionAPI/hdUltimateConfig.json b/HandsetDetectionAPI/hdUltimateConfig.json index cb0b37fd..be546d11 100644 --- a/HandsetDetectionAPI/hdUltimateConfig.json +++ b/HandsetDetectionAPI/hdUltimateConfig.json @@ -2,18 +2,18 @@ "username":"65ca2fe072", "secret":"RK4LzTcJHdq2C4cX", "site_id":"56163", - "use_local":true, + "use_local":"true", "filesdir":"C://APIData", - "debug":false, + "debug":"false", "api_server":"api.handsetdetection.com", - "cache_requests":false, - "geoip":true, - "timeout":10, - "use_proxy":false, + "cache_requests":"false", + "geoip":"true", + "timeout":"10", + "use_proxy":"false", "proxy_server":"", "proxy_port":"", "proxy_user":"", "proxy_pass":"", - "retries":3, - "log_unknown":true + "retries":"3", + "log_unknown":"true" } \ No newline at end of file diff --git a/HandsetDetectionAPIKit4/hdCloudConfig.json b/HandsetDetectionAPIKit4/hdCloudConfig.json index 672637b0..cee015e3 100644 --- a/HandsetDetectionAPIKit4/hdCloudConfig.json +++ b/HandsetDetectionAPIKit4/hdCloudConfig.json @@ -2,18 +2,18 @@ "username":"65ca2fe072", "secret":"RK4LzTcJHdq2C4cX", "site_id":"56163", - "use_local":false, + "use_local":"false", "filesdir":"", - "debug":false, + "debug":"false", "api_server":"api.handsetdetection.com", - "cache_requests":false, - "geoip":true, - "timeout":10, - "use_proxy":false, + "cache_requests":"false", + "geoip":"true", + "timeout":"10", + "use_proxy":"false", "proxy_server":"", "proxy_port":"", "proxy_user":"", "proxy_pass":"", - "retries":3, - "log_unknown":true + "retries":"3", + "log_unknown":"true" } \ No newline at end of file diff --git a/HandsetDetectionAPIKit4/hdUltimateConfig.json b/HandsetDetectionAPIKit4/hdUltimateConfig.json index c04a234d..7c8da7f7 100644 --- a/HandsetDetectionAPIKit4/hdUltimateConfig.json +++ b/HandsetDetectionAPIKit4/hdUltimateConfig.json @@ -2,18 +2,18 @@ "username":"65ca2fe072", "secret":"RK4LzTcJHdq2C4cX", "site_id":"56163", - "use_local":true, + "use_local":"true", "filesdir":"d://APIData", - "debug":false, + "debug":"false", "api_server":"api.handsetdetection.com", - "cache_requests":false, - "geoip":true, - "timeout":10, - "use_proxy":false, + "cache_requests":"false", + "geoip":"true", + "timeout":"10", + "use_proxy":"false", "proxy_server":"", "proxy_port":"", "proxy_user":"", "proxy_pass":"", - "retries":3, - "log_unknown":true + "retries":"3", + "log_unknown":"true" } \ No newline at end of file From 23487eeb6a64d75b4e4b6ba0fbba39ad9c28b697 Mon Sep 17 00:00:00 2001 From: Info Offbeat Date: Mon, 15 Feb 2016 18:23:15 +0530 Subject: [PATCH 5/5] Caching Issue Resolved --- HandsetDetectionAPI/HDCache.cs | 58 ++++++++++++++++++++++++++++----- HandsetDetectionAPI/HDDevice.cs | 54 ++++++++++++++++-------------- HandsetDetectionAPI/HDExtra.cs | 4 +-- HandsetDetectionAPI/HDStore.cs | 4 +-- 4 files changed, 83 insertions(+), 37 deletions(-) diff --git a/HandsetDetectionAPI/HDCache.cs b/HandsetDetectionAPI/HDCache.cs index 088b30b7..0b23fcda 100644 --- a/HandsetDetectionAPI/HDCache.cs +++ b/HandsetDetectionAPI/HDCache.cs @@ -1,10 +1,14 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; +using System.IO; using System.Linq; using System.Runtime.Caching; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Threading.Tasks; +using System.Web; using System.Web.Caching; using System.Web.Script.Serialization; @@ -13,20 +17,15 @@ namespace HandsetDetectionAPI public class HdCache { private static int _maxJsonLength = 40000000; - string _prefix = "hd4-"; + string _prefix = "hd4_"; //int duration = 7200; - ObjectCache _myCache; + readonly MemoryCache _myCache = MemoryCache.Default; CacheItemPolicy _policy = new CacheItemPolicy(); JavaScriptSerializer _jss = new JavaScriptSerializer { MaxJsonLength = _maxJsonLength }; public HdCache() { _policy.AbsoluteExpiration = new DateTimeOffset(DateTime.Now.AddHours(24)); - NameValueCollection cacheSettings = new NameValueCollection(3) - { - {"CacheMemoryLimitMegabytes", Convert.ToString(200)} - }; - _myCache = MemoryCache.Default; } public T Write(string key, T value) @@ -36,7 +35,7 @@ public T Write(string key, T value) { if (value != null && key != "") { - // string storethis = _jss.Serialize(value); + // var count = _myCache.Count(); _myCache.Set(_prefix + key, value, _policy); return value; } @@ -58,7 +57,13 @@ public T Read(string key) try { object fromCache = _myCache.Get(_prefix + key); - if (fromCache != null) return (T)Convert.ChangeType(fromCache, typeof(T)); + + + if (fromCache != null) + { + T item = (T)Convert.ChangeType(fromCache, typeof(T)); + return item.Clone(); + } } catch (Exception) { @@ -86,4 +91,39 @@ public bool Purge() } } + + /// + /// Provides a method for performing a deep copy of an object. + /// Binary Serialization is used to perform the copy. + /// + public static class ObjectCopier + { + /// + /// Perform a deep Copy of the object. + /// + /// The type of object being copied. + /// The object instance to copy./// The copied object. + public static T Clone(this T source) + { + if (!typeof(T).IsSerializable) + { + throw new ArgumentException("The type must be serializable.", "source"); + } + + // Don't serialize a null object, simply return the default for that object + if (Object.ReferenceEquals(source, null)) + { + return default(T); + } + + IFormatter formatter = new BinaryFormatter(); + Stream stream = new MemoryStream(); + using (stream) + { + formatter.Serialize(stream, source); + stream.Seek(0, SeekOrigin.Begin); + return (T)formatter.Deserialize(stream); + } + } + } } diff --git a/HandsetDetectionAPI/HDDevice.cs b/HandsetDetectionAPI/HDDevice.cs index 83717def..7a0946d1 100644 --- a/HandsetDetectionAPI/HDDevice.cs +++ b/HandsetDetectionAPI/HDDevice.cs @@ -318,7 +318,7 @@ public Dictionary FindRating(string deviceId, Dictionarystring specsField : Either "platform', 'browser', 'language' /// /// - public void SpecsOverlay(string specsField, ref dynamic device, Dictionary specs) + public Dictionary SpecsOverlay(string specsField, Dictionary device, Dictionary specs) { switch (specsField) { @@ -361,6 +361,7 @@ public void SpecsOverlay(string specsField, ref dynamic device, Dictionary @@ -406,11 +407,12 @@ private Dictionary InfoStringToArray(string hardwareInfo) /// /// /// - private void HardwareInfoOverlay(ref dynamic device, Dictionary infoArray) + private Dictionary HardwareInfoOverlay(Dictionary device, Dictionary infoArray) { device["Device"]["hd_ops"]["display_x"] = infoArray["display_x"]; device["Device"]["hd_ops"]["display_y"] = infoArray["display_y"]; device["Device"]["hd_ops"]["display_pixel_ratio"] = infoArray["display_pixel_ratio"]; + return device; } /// @@ -425,7 +427,7 @@ private void HardwareInfoOverlay(ref dynamic device, Dictionary /// /// /// array The matched device or null if not found - private dynamic MatchDevice(Dictionary headers) + private Dictionary MatchDevice(Dictionary headers) { // Opera mini sometimes puts the vendor # model in the header - nice! ... sometimes it puts ? # ? in as well if (headers.ContainsKey("x-operamini-phone") && headers["x-operamini-phone"].ToString() != "? # ?") @@ -494,7 +496,7 @@ private dynamic MatchDevice(Dictionary headers) return this.FindById(itemid); } - return false; + return null; } /// @@ -558,7 +560,9 @@ public dynamic V4MatchBuildInfo(Dictionary buildInfo) // Platform Detection dynamic platform = V4MatchBiHelper(buildInfo, "platform"); if (platform != null && platform.Count != 0) - this.SpecsOverlay("platform", ref device, platform["Extra"]); + { + device = this.SpecsOverlay("platform", device, platform["Extra"]); + } Reply["hd_specs"] = device["Device"]["hd_specs"]; return SetError(0, "OK"); @@ -695,9 +699,9 @@ private dynamic V4MatchHttpHeaders(Dictionary headers, string h } } - dynamic device = MatchDevice(deviceHeaders); + Dictionary device = MatchDevice(deviceHeaders); - if (device is bool) + if (device == null) { return SetError(301, "Not Found"); } @@ -715,7 +719,7 @@ private dynamic V4MatchHttpHeaders(Dictionary headers, string h { if (hwProps is IDictionary) { - HardwareInfoOverlay(ref device, (Dictionary)hwProps); + device = HardwareInfoOverlay(device, (Dictionary)hwProps); } } @@ -725,10 +729,10 @@ private dynamic V4MatchHttpHeaders(Dictionary headers, string h } // Get extra info - dynamic platform = _extra.MatchExtra("platform", extraHeaders); - dynamic browser = _extra.MatchExtra("browser", extraHeaders); - dynamic app = _extra.MatchExtra("app", extraHeaders); - dynamic language = _extra.MatchLanguage(extraHeaders); + Dictionary platform = _extra.MatchExtra("platform", extraHeaders); + Dictionary browser = _extra.MatchExtra("browser", extraHeaders); + Dictionary app = _extra.MatchExtra("app", extraHeaders); + Dictionary language = _extra.MatchLanguage(extraHeaders); // Find out if there is any contention on the detected rule. dynamic deviceList = GetHighAccuracyCandidates(); @@ -737,14 +741,14 @@ private dynamic V4MatchHttpHeaders(Dictionary headers, string h { List pass1List = new List(); // Resolve contention with OS check - if (!(platform is bool)) + if (platform != null) { _extra.Set(platform); foreach (dynamic item in deviceList) { - dynamic tryDevice = this.FindById(item); + Dictionary tryDevice = this.FindById(item); if (_extra.VerifyPlatform(tryDevice["Device"]["hd_specs"])) { @@ -772,7 +776,7 @@ private dynamic V4MatchHttpHeaders(Dictionary headers, string h // Sort the results //usort($result, array($this, 'hd_sortByScore')); Dictionary bestRatedDevice = GetDeviceFromRatingResult(result); - dynamic objDevice = this.FindById(bestRatedDevice["_id"]); + Dictionary objDevice = this.FindById(bestRatedDevice["_id"]); if (objDevice.Count > 0) { device = objDevice; @@ -782,25 +786,27 @@ private dynamic V4MatchHttpHeaders(Dictionary headers, string h } // Overlay specs - if (!(platform is bool)) + if (platform != null) { - SpecsOverlay("platform", ref device, platform["Extra"]); + device = SpecsOverlay("platform", device, platform["Extra"]); } - if (!(browser is bool)) + if (browser != null) { - SpecsOverlay("browser", ref device, browser["Extra"]); + device = SpecsOverlay("browser", device, browser["Extra"]); } - if (!(app is bool)) + if (app != null) { - SpecsOverlay("app", ref device, app["Extra"]); + device = SpecsOverlay("app", device, app["Extra"]); } - if (!(language is bool)) + if (language != null) { - SpecsOverlay("language", ref device, language["Extra"]); + device = SpecsOverlay("language", device, language["Extra"]); } // Overlay hardware info result if required if (device["Device"]["hd_ops"]["overlay_result_specs"].ToString() == "1" && !string.IsNullOrEmpty(hardwareInfo)) - HardwareInfoOverlay(ref device, hwProps); + { + device = HardwareInfoOverlay(device, hwProps); + } Reply["hd_specs"] = device["Device"]["hd_specs"]; return SetError(0, "OK");//for meantime diff --git a/HandsetDetectionAPI/HDExtra.cs b/HandsetDetectionAPI/HDExtra.cs index 30a6a1f2..243a14af 100644 --- a/HandsetDetectionAPI/HDExtra.cs +++ b/HandsetDetectionAPI/HDExtra.cs @@ -51,7 +51,7 @@ public dynamic MatchExtra(string className, Dictionary headers) return extra; } } - return false; + return null; } @@ -71,7 +71,7 @@ public dynamic FindById(string id) /// /// headers A key => value array of sanitized http headers /// array Extra on success, false otherwise - public dynamic MatchLanguage(Dictionary headers) + public Dictionary MatchLanguage(Dictionary headers) { Dictionary extra = new Dictionary(); // Mock up a fake Extra for merge into detection reply. diff --git a/HandsetDetectionAPI/HDStore.cs b/HandsetDetectionAPI/HDStore.cs index b878791c..f8e45564 100644 --- a/HandsetDetectionAPI/HDStore.cs +++ b/HandsetDetectionAPI/HDStore.cs @@ -130,7 +130,7 @@ public bool store(string key, Dictionary data) /// boolean true on success, false public T Read(string key) { - var reply = _cache.Read(key); + T reply = _cache.Read(key); if (reply != null) return reply; @@ -138,7 +138,7 @@ public T Read(string key) if (reply != null) { _cache.Write(key, reply); - return reply; + return reply.Clone(); } else {