Merge pull request #63 from humphd/zlib

Add zlib adapter
This commit is contained in:
Alan K 2013-12-06 08:53:19 -08:00
commit 2c872fd354
8 changed files with 241 additions and 28 deletions

View File

@ -143,21 +143,26 @@ IDBFS based file systems can acquire new functionality by using adapters. These
of storage providers without altering them in anway. An adapter can be used with any provider, and multiple of storage providers without altering them in anway. An adapter can be used with any provider, and multiple
adapters can be used together in order to compose complex functionality on top of a provider. adapters can be used together in order to compose complex functionality on top of a provider.
There are currently 4 adapters available: There are currently 5 adapters available:
* `FileSystem.adapters.Compression(provider)` - a default compression adapter that uses [Zlib](https://github.com/imaya/zlib.js)
* `FileSystem.adapters.Encryption(passphrase, provider)` - a default encryption adapter that uses [AES encryption](http://code.google.com/p/crypto-js/#AES)
You can also pick from other encryption cipher algorithms:
* `FileSystem.adapters.AES(passphrase, provider)` - extends a provider with [AES encryption](http://code.google.com/p/crypto-js/#AES) * `FileSystem.adapters.AES(passphrase, provider)` - extends a provider with [AES encryption](http://code.google.com/p/crypto-js/#AES)
* `FileSystem.adapters.TripleDES(passphrase, provider)` - extends a provider with [TripleDES encryption](http://code.google.com/p/crypto-js/#DES,_Triple_DES) * `FileSystem.adapters.TripleDES(passphrase, provider)` - extends a provider with [TripleDES encryption](http://code.google.com/p/crypto-js/#DES,_Triple_DES)
* `FileSystem.adapters.Rabbit(passphrase, provider)` - extends a provider with [Rabbit encryption](http://code.google.com/p/crypto-js/#Rabbit) * `FileSystem.adapters.Rabbit(passphrase, provider)` - extends a provider with [Rabbit encryption](http://code.google.com/p/crypto-js/#Rabbit)
* `FileSystem.adapters.Encryption(passphrase, provider)` - a default encryption adapter that uses [AES encryption](http://code.google.com/p/crypto-js/#AES)
```javascript ```javascript
var FileSystem = IDBFS.FileSystem; var FileSystem = IDBFS.FileSystem;
var providers = FileSystem.providers; var providers = FileSystem.providers;
var adapters = FileSystem.adapters; var adapters = FileSystem.adapters;
// Create a WebSQL-based, Encrypted File System. // Create a WebSQL-based, Encrypted, Compressed File System by
// composing a provider and adatpers.
var webSQLProvider = new providers.WebSQL(); var webSQLProvider = new providers.WebSQL();
var encryptionAdatper = new adapters.Encryption('super-secret-passphrase', webSQLProvider); var encryptionAdatper = new adapters.Encryption('super-secret-passphrase', webSQLProvider);
var fs1 = new FileSystem({ provider: encryptionAdapter }); var compressionAdatper = new adatpers.Compression(encryptionAdapter);
var fs = new FileSystem({ provider: compressionAdapter });
``` ```
You can also write your own adapter if you need to add new capabilities to the providers. Adapters share the same You can also write your own adapter if you need to add new capabilities to the providers. Adapters share the same

40
lib/zlib.js Normal file
View File

@ -0,0 +1,40 @@
/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';function l(d){throw d;}var u=void 0,x=!0,aa=this;function z(d,a){var c=d.split("."),f=aa;!(c[0]in f)&&f.execScript&&f.execScript("var "+c[0]);for(var b;c.length&&(b=c.shift());)!c.length&&a!==u?f[b]=a:f=f[b]?f[b]:f[b]={}};var E="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array;function G(d,a){this.index="number"===typeof a?a:0;this.i=0;this.buffer=d instanceof(E?Uint8Array:Array)?d:new (E?Uint8Array:Array)(32768);2*this.buffer.length<=this.index&&l(Error("invalid index"));this.buffer.length<=this.index&&this.f()}G.prototype.f=function(){var d=this.buffer,a,c=d.length,f=new (E?Uint8Array:Array)(c<<1);if(E)f.set(d);else for(a=0;a<c;++a)f[a]=d[a];return this.buffer=f};
G.prototype.d=function(d,a,c){var f=this.buffer,b=this.index,e=this.i,g=f[b],h;c&&1<a&&(d=8<a?(N[d&255]<<24|N[d>>>8&255]<<16|N[d>>>16&255]<<8|N[d>>>24&255])>>32-a:N[d]>>8-a);if(8>a+e)g=g<<a|d,e+=a;else for(h=0;h<a;++h)g=g<<1|d>>a-h-1&1,8===++e&&(e=0,f[b++]=N[g],g=0,b===f.length&&(f=this.f()));f[b]=g;this.buffer=f;this.i=e;this.index=b};G.prototype.finish=function(){var d=this.buffer,a=this.index,c;0<this.i&&(d[a]<<=8-this.i,d[a]=N[d[a]],a++);E?c=d.subarray(0,a):(d.length=a,c=d);return c};
var fa=new (E?Uint8Array:Array)(256),O;for(O=0;256>O;++O){for(var P=O,Q=P,ga=7,P=P>>>1;P;P>>>=1)Q<<=1,Q|=P&1,--ga;fa[O]=(Q<<ga&255)>>>0}var N=fa;function ha(d){this.buffer=new (E?Uint16Array:Array)(2*d);this.length=0}ha.prototype.getParent=function(d){return 2*((d-2)/4|0)};ha.prototype.push=function(d,a){var c,f,b=this.buffer,e;c=this.length;b[this.length++]=a;for(b[this.length++]=d;0<c;)if(f=this.getParent(c),b[c]>b[f])e=b[c],b[c]=b[f],b[f]=e,e=b[c+1],b[c+1]=b[f+1],b[f+1]=e,c=f;else break;return this.length};
ha.prototype.pop=function(){var d,a,c=this.buffer,f,b,e;a=c[0];d=c[1];this.length-=2;c[0]=c[this.length];c[1]=c[this.length+1];for(e=0;;){b=2*e+2;if(b>=this.length)break;b+2<this.length&&c[b+2]>c[b]&&(b+=2);if(c[b]>c[e])f=c[e],c[e]=c[b],c[b]=f,f=c[e+1],c[e+1]=c[b+1],c[b+1]=f;else break;e=b}return{index:d,value:a,length:this.length}};function R(d){var a=d.length,c=0,f=Number.POSITIVE_INFINITY,b,e,g,h,k,n,q,r,p;for(r=0;r<a;++r)d[r]>c&&(c=d[r]),d[r]<f&&(f=d[r]);b=1<<c;e=new (E?Uint32Array:Array)(b);g=1;h=0;for(k=2;g<=c;){for(r=0;r<a;++r)if(d[r]===g){n=0;q=h;for(p=0;p<g;++p)n=n<<1|q&1,q>>=1;for(p=n;p<b;p+=k)e[p]=g<<16|r;++h}++g;h<<=1;k<<=1}return[e,c,f]};function ia(d,a){this.h=ma;this.w=0;this.input=E&&d instanceof Array?new Uint8Array(d):d;this.b=0;a&&(a.lazy&&(this.w=a.lazy),"number"===typeof a.compressionType&&(this.h=a.compressionType),a.outputBuffer&&(this.a=E&&a.outputBuffer instanceof Array?new Uint8Array(a.outputBuffer):a.outputBuffer),"number"===typeof a.outputIndex&&(this.b=a.outputIndex));this.a||(this.a=new (E?Uint8Array:Array)(32768))}var ma=2,na={NONE:0,r:1,k:ma,N:3},oa=[],S;
for(S=0;288>S;S++)switch(x){case 143>=S:oa.push([S+48,8]);break;case 255>=S:oa.push([S-144+400,9]);break;case 279>=S:oa.push([S-256+0,7]);break;case 287>=S:oa.push([S-280+192,8]);break;default:l("invalid literal: "+S)}
ia.prototype.j=function(){var d,a,c,f,b=this.input;switch(this.h){case 0:c=0;for(f=b.length;c<f;){a=E?b.subarray(c,c+65535):b.slice(c,c+65535);c+=a.length;var e=a,g=c===f,h=u,k=u,n=u,q=u,r=u,p=this.a,m=this.b;if(E){for(p=new Uint8Array(this.a.buffer);p.length<=m+e.length+5;)p=new Uint8Array(p.length<<1);p.set(this.a)}h=g?1:0;p[m++]=h|0;k=e.length;n=~k+65536&65535;p[m++]=k&255;p[m++]=k>>>8&255;p[m++]=n&255;p[m++]=n>>>8&255;if(E)p.set(e,m),m+=e.length,p=p.subarray(0,m);else{q=0;for(r=e.length;q<r;++q)p[m++]=
e[q];p.length=m}this.b=m;this.a=p}break;case 1:var s=new G(E?new Uint8Array(this.a.buffer):this.a,this.b);s.d(1,1,x);s.d(1,2,x);var w=pa(this,b),y,ja,B;y=0;for(ja=w.length;y<ja;y++)if(B=w[y],G.prototype.d.apply(s,oa[B]),256<B)s.d(w[++y],w[++y],x),s.d(w[++y],5),s.d(w[++y],w[++y],x);else if(256===B)break;this.a=s.finish();this.b=this.a.length;break;case ma:var D=new G(E?new Uint8Array(this.a.buffer):this.a,this.b),Da,M,U,V,W,gb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],ba,Ea,ca,Fa,ka,ra=Array(19),
Ga,X,la,A,Ha;Da=ma;D.d(1,1,x);D.d(Da,2,x);M=pa(this,b);ba=qa(this.L,15);Ea=sa(ba);ca=qa(this.K,7);Fa=sa(ca);for(U=286;257<U&&0===ba[U-1];U--);for(V=30;1<V&&0===ca[V-1];V--);var Ia=U,Ja=V,I=new (E?Uint32Array:Array)(Ia+Ja),t,J,v,da,H=new (E?Uint32Array:Array)(316),F,C,K=new (E?Uint8Array:Array)(19);for(t=J=0;t<Ia;t++)I[J++]=ba[t];for(t=0;t<Ja;t++)I[J++]=ca[t];if(!E){t=0;for(da=K.length;t<da;++t)K[t]=0}t=F=0;for(da=I.length;t<da;t+=J){for(J=1;t+J<da&&I[t+J]===I[t];++J);v=J;if(0===I[t])if(3>v)for(;0<
v--;)H[F++]=0,K[0]++;else for(;0<v;)C=138>v?v:138,C>v-3&&C<v&&(C=v-3),10>=C?(H[F++]=17,H[F++]=C-3,K[17]++):(H[F++]=18,H[F++]=C-11,K[18]++),v-=C;else if(H[F++]=I[t],K[I[t]]++,v--,3>v)for(;0<v--;)H[F++]=I[t],K[I[t]]++;else for(;0<v;)C=6>v?v:6,C>v-3&&C<v&&(C=v-3),H[F++]=16,H[F++]=C-3,K[16]++,v-=C}d=E?H.subarray(0,F):H.slice(0,F);ka=qa(K,7);for(A=0;19>A;A++)ra[A]=ka[gb[A]];for(W=19;4<W&&0===ra[W-1];W--);Ga=sa(ka);D.d(U-257,5,x);D.d(V-1,5,x);D.d(W-4,4,x);for(A=0;A<W;A++)D.d(ra[A],3,x);A=0;for(Ha=d.length;A<
Ha;A++)if(X=d[A],D.d(Ga[X],ka[X],x),16<=X){A++;switch(X){case 16:la=2;break;case 17:la=3;break;case 18:la=7;break;default:l("invalid code: "+X)}D.d(d[A],la,x)}var Ka=[Ea,ba],La=[Fa,ca],L,Ma,ea,ua,Na,Oa,Pa,Qa;Na=Ka[0];Oa=Ka[1];Pa=La[0];Qa=La[1];L=0;for(Ma=M.length;L<Ma;++L)if(ea=M[L],D.d(Na[ea],Oa[ea],x),256<ea)D.d(M[++L],M[++L],x),ua=M[++L],D.d(Pa[ua],Qa[ua],x),D.d(M[++L],M[++L],x);else if(256===ea)break;this.a=D.finish();this.b=this.a.length;break;default:l("invalid compression type")}return this.a};
function ta(d,a){this.length=d;this.G=a}
var va=function(){function d(b){switch(x){case 3===b:return[257,b-3,0];case 4===b:return[258,b-4,0];case 5===b:return[259,b-5,0];case 6===b:return[260,b-6,0];case 7===b:return[261,b-7,0];case 8===b:return[262,b-8,0];case 9===b:return[263,b-9,0];case 10===b:return[264,b-10,0];case 12>=b:return[265,b-11,1];case 14>=b:return[266,b-13,1];case 16>=b:return[267,b-15,1];case 18>=b:return[268,b-17,1];case 22>=b:return[269,b-19,2];case 26>=b:return[270,b-23,2];case 30>=b:return[271,b-27,2];case 34>=b:return[272,
b-31,2];case 42>=b:return[273,b-35,3];case 50>=b:return[274,b-43,3];case 58>=b:return[275,b-51,3];case 66>=b:return[276,b-59,3];case 82>=b:return[277,b-67,4];case 98>=b:return[278,b-83,4];case 114>=b:return[279,b-99,4];case 130>=b:return[280,b-115,4];case 162>=b:return[281,b-131,5];case 194>=b:return[282,b-163,5];case 226>=b:return[283,b-195,5];case 257>=b:return[284,b-227,5];case 258===b:return[285,b-258,0];default:l("invalid length: "+b)}}var a=[],c,f;for(c=3;258>=c;c++)f=d(c),a[c]=f[2]<<24|f[1]<<
16|f[0];return a}(),wa=E?new Uint32Array(va):va;
function pa(d,a){function c(b,c){var a=b.G,d=[],e=0,f;f=wa[b.length];d[e++]=f&65535;d[e++]=f>>16&255;d[e++]=f>>24;var g;switch(x){case 1===a:g=[0,a-1,0];break;case 2===a:g=[1,a-2,0];break;case 3===a:g=[2,a-3,0];break;case 4===a:g=[3,a-4,0];break;case 6>=a:g=[4,a-5,1];break;case 8>=a:g=[5,a-7,1];break;case 12>=a:g=[6,a-9,2];break;case 16>=a:g=[7,a-13,2];break;case 24>=a:g=[8,a-17,3];break;case 32>=a:g=[9,a-25,3];break;case 48>=a:g=[10,a-33,4];break;case 64>=a:g=[11,a-49,4];break;case 96>=a:g=[12,a-
65,5];break;case 128>=a:g=[13,a-97,5];break;case 192>=a:g=[14,a-129,6];break;case 256>=a:g=[15,a-193,6];break;case 384>=a:g=[16,a-257,7];break;case 512>=a:g=[17,a-385,7];break;case 768>=a:g=[18,a-513,8];break;case 1024>=a:g=[19,a-769,8];break;case 1536>=a:g=[20,a-1025,9];break;case 2048>=a:g=[21,a-1537,9];break;case 3072>=a:g=[22,a-2049,10];break;case 4096>=a:g=[23,a-3073,10];break;case 6144>=a:g=[24,a-4097,11];break;case 8192>=a:g=[25,a-6145,11];break;case 12288>=a:g=[26,a-8193,12];break;case 16384>=
a:g=[27,a-12289,12];break;case 24576>=a:g=[28,a-16385,13];break;case 32768>=a:g=[29,a-24577,13];break;default:l("invalid distance")}f=g;d[e++]=f[0];d[e++]=f[1];d[e++]=f[2];var h,k;h=0;for(k=d.length;h<k;++h)p[m++]=d[h];w[d[0]]++;y[d[3]]++;s=b.length+c-1;r=null}var f,b,e,g,h,k={},n,q,r,p=E?new Uint16Array(2*a.length):[],m=0,s=0,w=new (E?Uint32Array:Array)(286),y=new (E?Uint32Array:Array)(30),ja=d.w,B;if(!E){for(e=0;285>=e;)w[e++]=0;for(e=0;29>=e;)y[e++]=0}w[256]=1;f=0;for(b=a.length;f<b;++f){e=h=0;
for(g=3;e<g&&f+e!==b;++e)h=h<<8|a[f+e];k[h]===u&&(k[h]=[]);n=k[h];if(!(0<s--)){for(;0<n.length&&32768<f-n[0];)n.shift();if(f+3>=b){r&&c(r,-1);e=0;for(g=b-f;e<g;++e)B=a[f+e],p[m++]=B,++w[B];break}0<n.length?(q=xa(a,f,n),r?r.length<q.length?(B=a[f-1],p[m++]=B,++w[B],c(q,0)):c(r,-1):q.length<ja?r=q:c(q,0)):r?c(r,-1):(B=a[f],p[m++]=B,++w[B])}n.push(f)}p[m++]=256;w[256]++;d.L=w;d.K=y;return E?p.subarray(0,m):p}
function xa(d,a,c){var f,b,e=0,g,h,k,n,q=d.length;h=0;n=c.length;a:for(;h<n;h++){f=c[n-h-1];g=3;if(3<e){for(k=e;3<k;k--)if(d[f+k-1]!==d[a+k-1])continue a;g=e}for(;258>g&&a+g<q&&d[f+g]===d[a+g];)++g;g>e&&(b=f,e=g);if(258===g)break}return new ta(e,a-b)}
function qa(d,a){var c=d.length,f=new ha(572),b=new (E?Uint8Array:Array)(c),e,g,h,k,n;if(!E)for(k=0;k<c;k++)b[k]=0;for(k=0;k<c;++k)0<d[k]&&f.push(k,d[k]);e=Array(f.length/2);g=new (E?Uint32Array:Array)(f.length/2);if(1===e.length)return b[f.pop().index]=1,b;k=0;for(n=f.length/2;k<n;++k)e[k]=f.pop(),g[k]=e[k].value;h=ya(g,g.length,a);k=0;for(n=e.length;k<n;++k)b[e[k].index]=h[k];return b}
function ya(d,a,c){function f(b){var c=k[b][n[b]];c===a?(f(b+1),f(b+1)):--g[c];++n[b]}var b=new (E?Uint16Array:Array)(c),e=new (E?Uint8Array:Array)(c),g=new (E?Uint8Array:Array)(a),h=Array(c),k=Array(c),n=Array(c),q=(1<<c)-a,r=1<<c-1,p,m,s,w,y;b[c-1]=a;for(m=0;m<c;++m)q<r?e[m]=0:(e[m]=1,q-=r),q<<=1,b[c-2-m]=(b[c-1-m]/2|0)+a;b[0]=e[0];h[0]=Array(b[0]);k[0]=Array(b[0]);for(m=1;m<c;++m)b[m]>2*b[m-1]+e[m]&&(b[m]=2*b[m-1]+e[m]),h[m]=Array(b[m]),k[m]=Array(b[m]);for(p=0;p<a;++p)g[p]=c;for(s=0;s<b[c-1];++s)h[c-
1][s]=d[s],k[c-1][s]=s;for(p=0;p<c;++p)n[p]=0;1===e[c-1]&&(--g[0],++n[c-1]);for(m=c-2;0<=m;--m){w=p=0;y=n[m+1];for(s=0;s<b[m];s++)w=h[m+1][y]+h[m+1][y+1],w>d[p]?(h[m][s]=w,k[m][s]=a,y+=2):(h[m][s]=d[p],k[m][s]=p,++p);n[m]=0;1===e[m]&&f(m)}return g}
function sa(d){var a=new (E?Uint16Array:Array)(d.length),c=[],f=[],b=0,e,g,h,k;e=0;for(g=d.length;e<g;e++)c[d[e]]=(c[d[e]]|0)+1;e=1;for(g=16;e<=g;e++)f[e]=b,b+=c[e]|0,b<<=1;e=0;for(g=d.length;e<g;e++){b=f[d[e]];f[d[e]]+=1;h=a[e]=0;for(k=d[e];h<k;h++)a[e]=a[e]<<1|b&1,b>>>=1}return a};function T(d,a){this.l=[];this.m=32768;this.e=this.g=this.c=this.q=0;this.input=E?new Uint8Array(d):d;this.s=!1;this.n=za;this.B=!1;if(a||!(a={}))a.index&&(this.c=a.index),a.bufferSize&&(this.m=a.bufferSize),a.bufferType&&(this.n=a.bufferType),a.resize&&(this.B=a.resize);switch(this.n){case Aa:this.b=32768;this.a=new (E?Uint8Array:Array)(32768+this.m+258);break;case za:this.b=0;this.a=new (E?Uint8Array:Array)(this.m);this.f=this.J;this.t=this.H;this.o=this.I;break;default:l(Error("invalid inflate mode"))}}
var Aa=0,za=1,Ba={D:Aa,C:za};
T.prototype.p=function(){for(;!this.s;){var d=Y(this,3);d&1&&(this.s=x);d>>>=1;switch(d){case 0:var a=this.input,c=this.c,f=this.a,b=this.b,e=u,g=u,h=u,k=f.length,n=u;this.e=this.g=0;e=a[c++];e===u&&l(Error("invalid uncompressed block header: LEN (first byte)"));g=e;e=a[c++];e===u&&l(Error("invalid uncompressed block header: LEN (second byte)"));g|=e<<8;e=a[c++];e===u&&l(Error("invalid uncompressed block header: NLEN (first byte)"));h=e;e=a[c++];e===u&&l(Error("invalid uncompressed block header: NLEN (second byte)"));h|=
e<<8;g===~h&&l(Error("invalid uncompressed block header: length verify"));c+g>a.length&&l(Error("input buffer is broken"));switch(this.n){case Aa:for(;b+g>f.length;){n=k-b;g-=n;if(E)f.set(a.subarray(c,c+n),b),b+=n,c+=n;else for(;n--;)f[b++]=a[c++];this.b=b;f=this.f();b=this.b}break;case za:for(;b+g>f.length;)f=this.f({v:2});break;default:l(Error("invalid inflate mode"))}if(E)f.set(a.subarray(c,c+g),b),b+=g,c+=g;else for(;g--;)f[b++]=a[c++];this.c=c;this.b=b;this.a=f;break;case 1:this.o(Ca,Ra);break;
case 2:Sa(this);break;default:l(Error("unknown BTYPE: "+d))}}return this.t()};
var Ta=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],Ua=E?new Uint16Array(Ta):Ta,Va=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],Wa=E?new Uint16Array(Va):Va,Xa=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],Ya=E?new Uint8Array(Xa):Xa,Za=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],$a=E?new Uint16Array(Za):Za,ab=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,
10,11,11,12,12,13,13],bb=E?new Uint8Array(ab):ab,cb=new (E?Uint8Array:Array)(288),Z,db;Z=0;for(db=cb.length;Z<db;++Z)cb[Z]=143>=Z?8:255>=Z?9:279>=Z?7:8;var Ca=R(cb),eb=new (E?Uint8Array:Array)(30),fb,hb;fb=0;for(hb=eb.length;fb<hb;++fb)eb[fb]=5;var Ra=R(eb);function Y(d,a){for(var c=d.g,f=d.e,b=d.input,e=d.c,g;f<a;)g=b[e++],g===u&&l(Error("input buffer is broken")),c|=g<<f,f+=8;g=c&(1<<a)-1;d.g=c>>>a;d.e=f-a;d.c=e;return g}
function ib(d,a){for(var c=d.g,f=d.e,b=d.input,e=d.c,g=a[0],h=a[1],k,n,q;f<h;){k=b[e++];if(k===u)break;c|=k<<f;f+=8}n=g[c&(1<<h)-1];q=n>>>16;d.g=c>>q;d.e=f-q;d.c=e;return n&65535}
function Sa(d){function a(a,b,c){var d,f,e,g;for(g=0;g<a;)switch(d=ib(this,b),d){case 16:for(e=3+Y(this,2);e--;)c[g++]=f;break;case 17:for(e=3+Y(this,3);e--;)c[g++]=0;f=0;break;case 18:for(e=11+Y(this,7);e--;)c[g++]=0;f=0;break;default:f=c[g++]=d}return c}var c=Y(d,5)+257,f=Y(d,5)+1,b=Y(d,4)+4,e=new (E?Uint8Array:Array)(Ua.length),g,h,k,n;for(n=0;n<b;++n)e[Ua[n]]=Y(d,3);g=R(e);h=new (E?Uint8Array:Array)(c);k=new (E?Uint8Array:Array)(f);d.o(R(a.call(d,c,g,h)),R(a.call(d,f,g,k)))}
T.prototype.o=function(d,a){var c=this.a,f=this.b;this.u=d;for(var b=c.length-258,e,g,h,k;256!==(e=ib(this,d));)if(256>e)f>=b&&(this.b=f,c=this.f(),f=this.b),c[f++]=e;else{g=e-257;k=Wa[g];0<Ya[g]&&(k+=Y(this,Ya[g]));e=ib(this,a);h=$a[e];0<bb[e]&&(h+=Y(this,bb[e]));f>=b&&(this.b=f,c=this.f(),f=this.b);for(;k--;)c[f]=c[f++-h]}for(;8<=this.e;)this.e-=8,this.c--;this.b=f};
T.prototype.I=function(d,a){var c=this.a,f=this.b;this.u=d;for(var b=c.length,e,g,h,k;256!==(e=ib(this,d));)if(256>e)f>=b&&(c=this.f(),b=c.length),c[f++]=e;else{g=e-257;k=Wa[g];0<Ya[g]&&(k+=Y(this,Ya[g]));e=ib(this,a);h=$a[e];0<bb[e]&&(h+=Y(this,bb[e]));f+k>b&&(c=this.f(),b=c.length);for(;k--;)c[f]=c[f++-h]}for(;8<=this.e;)this.e-=8,this.c--;this.b=f};
T.prototype.f=function(){var d=new (E?Uint8Array:Array)(this.b-32768),a=this.b-32768,c,f,b=this.a;if(E)d.set(b.subarray(32768,d.length));else{c=0;for(f=d.length;c<f;++c)d[c]=b[c+32768]}this.l.push(d);this.q+=d.length;if(E)b.set(b.subarray(a,a+32768));else for(c=0;32768>c;++c)b[c]=b[a+c];this.b=32768;return b};
T.prototype.J=function(d){var a,c=this.input.length/this.c+1|0,f,b,e,g=this.input,h=this.a;d&&("number"===typeof d.v&&(c=d.v),"number"===typeof d.F&&(c+=d.F));2>c?(f=(g.length-this.c)/this.u[2],e=258*(f/2)|0,b=e<h.length?h.length+e:h.length<<1):b=h.length*c;E?(a=new Uint8Array(b),a.set(h)):a=h;return this.a=a};
T.prototype.t=function(){var d=0,a=this.a,c=this.l,f,b=new (E?Uint8Array:Array)(this.q+(this.b-32768)),e,g,h,k;if(0===c.length)return E?this.a.subarray(32768,this.b):this.a.slice(32768,this.b);e=0;for(g=c.length;e<g;++e){f=c[e];h=0;for(k=f.length;h<k;++h)b[d++]=f[h]}e=32768;for(g=this.b;e<g;++e)b[d++]=a[e];this.l=[];return this.buffer=b};
T.prototype.H=function(){var d,a=this.b;E?this.B?(d=new Uint8Array(a),d.set(this.a.subarray(0,a))):d=this.a.subarray(0,a):(this.a.length>a&&(this.a.length=a),d=this.a);return this.buffer=d};function jb(d){if("string"===typeof d){var a=d.split(""),c,f;c=0;for(f=a.length;c<f;c++)a[c]=(a[c].charCodeAt(0)&255)>>>0;d=a}for(var b=1,e=0,g=d.length,h,k=0;0<g;){h=1024<g?1024:g;g-=h;do b+=d[k++],e+=b;while(--h);b%=65521;e%=65521}return(e<<16|b)>>>0};function kb(d,a){var c,f;this.input=d;this.c=0;if(a||!(a={}))a.index&&(this.c=a.index),a.verify&&(this.M=a.verify);c=d[this.c++];f=d[this.c++];switch(c&15){case lb:this.method=lb;break;default:l(Error("unsupported compression method"))}0!==((c<<8)+f)%31&&l(Error("invalid fcheck flag:"+((c<<8)+f)%31));f&32&&l(Error("fdict flag is not supported"));this.A=new T(d,{index:this.c,bufferSize:a.bufferSize,bufferType:a.bufferType,resize:a.resize})}
kb.prototype.p=function(){var d=this.input,a,c;a=this.A.p();this.c=this.A.c;this.M&&(c=(d[this.c++]<<24|d[this.c++]<<16|d[this.c++]<<8|d[this.c++])>>>0,c!==jb(a)&&l(Error("invalid adler-32 checksum")));return a};var lb=8;function mb(d,a){this.input=d;this.a=new (E?Uint8Array:Array)(32768);this.h=$.k;var c={},f;if((a||!(a={}))&&"number"===typeof a.compressionType)this.h=a.compressionType;for(f in a)c[f]=a[f];c.outputBuffer=this.a;this.z=new ia(this.input,c)}var $=na;
mb.prototype.j=function(){var d,a,c,f,b,e,g,h=0;g=this.a;d=lb;switch(d){case lb:a=Math.LOG2E*Math.log(32768)-8;break;default:l(Error("invalid compression method"))}c=a<<4|d;g[h++]=c;switch(d){case lb:switch(this.h){case $.NONE:b=0;break;case $.r:b=1;break;case $.k:b=2;break;default:l(Error("unsupported compression type"))}break;default:l(Error("invalid compression method"))}f=b<<6|0;g[h++]=f|31-(256*c+f)%31;e=jb(this.input);this.z.b=h;g=this.z.j();h=g.length;E&&(g=new Uint8Array(g.buffer),g.length<=
h+4&&(this.a=new Uint8Array(g.length+4),this.a.set(g),g=this.a),g=g.subarray(0,h+4));g[h++]=e>>24&255;g[h++]=e>>16&255;g[h++]=e>>8&255;g[h++]=e&255;return g};function nb(d,a){var c,f,b,e;if(Object.keys)c=Object.keys(a);else for(f in c=[],b=0,a)c[b++]=f;b=0;for(e=c.length;b<e;++b)f=c[b],z(d+"."+f,a[f])};z("Zlib.Inflate",kb);z("Zlib.Inflate.prototype.decompress",kb.prototype.p);nb("Zlib.Inflate.BufferType",{ADAPTIVE:Ba.C,BLOCK:Ba.D});z("Zlib.Deflate",mb);z("Zlib.Deflate.compress",function(d,a){return(new mb(d,a)).j()});z("Zlib.Deflate.prototype.compress",mb.prototype.j);nb("Zlib.Deflate.CompressionType",{NONE:$.NONE,FIXED:$.r,DYNAMIC:$.k});}).call(this);

View File

@ -1,6 +1,7 @@
define(function(require) { define(function(require) {
var CryptoAdapters = require('src/adapters/crypto'); var CryptoAdapters = require('src/adapters/crypto');
var ZlibAdapter = require('src/adapters/zlib');
return { return {
@ -8,7 +9,12 @@ define(function(require) {
AES: CryptoAdapters.AES, AES: CryptoAdapters.AES,
TripleDES: CryptoAdapters.TripleDES, TripleDES: CryptoAdapters.TripleDES,
Rabbit: CryptoAdapters.Rabbit, Rabbit: CryptoAdapters.Rabbit,
// Convenience encryption wrapper (default to AES)
// Compression Adapters
Zlib: ZlibAdapter,
// Convenience adapters (provide default choices)
Compression: ZlibAdapter,
Encryption: CryptoAdapters.AES Encryption: CryptoAdapters.AES
}; };

View File

@ -8,6 +8,41 @@ define(function(require) {
require("crypto-js/rollups/rabbit"); require("crypto-js/rollups/rabbit");
// Move back and forth from Uint8Arrays and CryptoJS WordArray
// See http://code.google.com/p/crypto-js/#The_Cipher_Input and
// https://groups.google.com/forum/#!topic/crypto-js/TOb92tcJlU0
var WordArray = CryptoJS.lib.WordArray;
function fromWordArray(wordArray) {
var words = wordArray.words;
var sigBytes = wordArray.sigBytes;
var u8 = new Uint8Array(sigBytes);
var b;
for (var i = 0; i < sigBytes; i++) {
b = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
u8[i] = b;
}
return u8;
}
function toWordArray(u8arr) {
var len = u8arr.length;
var words = [];
for (var i = 0; i < len; i++) {
words[i >>> 2] |= (u8arr[i] & 0xff) << (24 - (i % 4) * 8);
}
return WordArray.create(words, len);
}
// UTF8 Text De/Encoders
require('encoding');
function encode(str) {
return (new TextEncoder('utf-8')).encode(str);
}
function decode(u8arr) {
return (new TextDecoder('utf-8')).decode(u8arr);
}
function CryptoContext(context, encrypt, decrypt) { function CryptoContext(context, encrypt, decrypt) {
this.context = context; this.context = context;
this.encrypt = encrypt; this.encrypt = encrypt;
@ -43,13 +78,34 @@ define(function(require) {
// prompting the user to enter it when the file system is being opened. // prompting the user to enter it when the file system is being opened.
function CryptoAdapter(passphrase, provider) { function CryptoAdapter(passphrase, provider) {
this.provider = provider; this.provider = provider;
this.encrypt = function(plain) {
return CryptoJS[encryptionType].encrypt(plain, passphrase) // Cache cipher algorithm we'll use in encrypt/decrypt
.toString(); var cipher = CryptoJS[encryptionType];
// To encrypt:
// 1) accept a buffer (Uint8Array) containing binary data
// 2) convert the buffer to a CipherJS WordArray
// 3) encrypt the WordArray using the chosen cipher algorithm + passphrase
// 4) convert the resulting ciphertext to a UTF8 encoded Uint8Array and return
this.encrypt = function(buffer) {
var wordArray = toWordArray(buffer);
var encrypted = cipher.encrypt(wordArray, passphrase);
var utf8EncodedBuf = encode(encrypted);
return utf8EncodedBuf;
}; };
this.decrypt = function(encrypted) {
return CryptoJS[encryptionType].decrypt(encrypted, passphrase) // To decrypt:
.toString(CryptoJS.enc.Utf8); // 1) accept a buffer (Uint8Array) containing a UTF8 encoded Uint8Array
// 2) convert the buffer to string (i.e., the ciphertext we got from encrypting)
// 3) decrypt the ciphertext string
// 4) convert the decrypted cipherParam object to a UTF8 string
// 5) encode the UTF8 string to a Uint8Array buffer and return
this.decrypt = function(buffer) {
var encryptedStr = decode(buffer);
var decrypted = cipher.decrypt(encryptedStr, passphrase);
var decryptedUtf8 = decrypted.toString(CryptoJS.enc.Utf8);
var utf8EncodedBuf = encode(decryptedUtf8);
return utf8EncodedBuf;
}; };
} }
CryptoAdapter.isSupported = function() { CryptoAdapter.isSupported = function() {

63
src/adapters/zlib.js Normal file
View File

@ -0,0 +1,63 @@
define(function(require) {
// Zlib compression, see
// https://github.com/imaya/zlib.js/blob/master/bin/zlib.min.js
require("zlib");
var Inflate = Zlib.Inflate;
function inflate(compressed) {
return (new Inflate(compressed)).decompress();
}
var Deflate = Zlib.Deflate;
function deflate(buffer) {
return (new Deflate(buffer)).compress();
}
function ZlibContext(context) {
this.context = context;
}
ZlibContext.prototype.clear = function(callback) {
this.context.clear(callback);
};
ZlibContext.prototype.get = function(key, callback) {
this.context.get(key, function(err, result) {
if(err) {
callback(err);
return;
}
// Deal with result being null
if(result) {
result = inflate(result);
}
callback(null, result);
});
};
ZlibContext.prototype.put = function(key, value, callback) {
value = deflate(value);
this.context.put(key, value, callback);
};
ZlibContext.prototype.delete = function(key, callback) {
this.context.delete(key, callback);
};
function ZlibAdapter(provider, inflate, deflate) {
this.provider = provider;
}
ZlibAdapter.isSupported = function() {
return true;
};
ZlibAdapter.prototype.open = function(callback) {
this.provider.open(callback);
};
ZlibAdapter.prototype.getReadOnlyContext = function() {
return new ZlibContext(this.provider.getReadOnlyContext());
};
ZlibAdapter.prototype.getReadWriteContext = function() {
return new ZlibContext(this.provider.getReadWriteContext());
};
return ZlibAdapter;
});

View File

@ -1,20 +1,31 @@
define(["IDBFS"], function(IDBFS) { define(["IDBFS"], function(IDBFS) {
// We reuse the same set of tests for all crypto adapters. // We reuse the same set of tests for all adapters.
// buildTestsFor() creates a set of tests bound to a crypto // buildTestsFor() creates a set of tests bound to an
// adapter, and uses a Memory() provider internally. // adapter, and uses a Memory() provider internally.
function buildTestsFor(adapterName) { function buildTestsFor(adapterName, buildAdapter) {
var passphrase = '' + Date.now(); function encode(str) {
// TextEncoder is either native, or shimmed by IDBFS
return (new TextEncoder("utf-8")).encode(str);
}
// Make some string + binary buffer versions of things we'll need
var valueStr = "value", valueBuffer = encode(valueStr);
var value1Str = "value1", value1Buffer = encode(value1Str);
var value2Str = "value2", value2Buffer = encode(value2Str);
function createProvider() { function createProvider() {
var memoryProvider = new IDBFS.FileSystem.providers.Memory(); var memoryProvider = new IDBFS.FileSystem.providers.Memory();
return new IDBFS.FileSystem.adapters[adapterName](passphrase, memoryProvider); return buildAdapter(memoryProvider);
} }
describe("IDBFS.FileSystem.adapters." + adapterName, function() { describe("IDBFS.FileSystem.adapters." + adapterName, function() {
it("is supported -- if it isn't, none of these tests can run.", function() { it("is supported -- if it isn't, none of these tests can run.", function() {
expect(IDBFS.FileSystem.adapters[adapterName].isSupported()).toEqual(true); // Allow for combined adapters (e.g., 'AES+Zlib') joined by '+'
adapterName.split('+').forEach(function(name) {
expect(IDBFS.FileSystem.adapters[name].isSupported()).toEqual(true);
});
}); });
it("has open, getReadOnlyContext, and getReadWriteContext instance methods", function() { it("has open, getReadOnlyContext, and getReadWriteContext instance methods", function() {
@ -47,7 +58,7 @@ define(["IDBFS"], function(IDBFS) {
}); });
}); });
describe("Read/Write operations on a Memory provider with an " + adapterName + "adapter", function() { describe("Read/Write operations on a Memory provider with an " + adapterName + " adapter", function() {
it("should allow put() and get()", function() { it("should allow put() and get()", function() {
var complete = false; var complete = false;
var _error, _result; var _error, _result;
@ -57,7 +68,7 @@ define(["IDBFS"], function(IDBFS) {
_error = err; _error = err;
var context = provider.getReadWriteContext(); var context = provider.getReadWriteContext();
context.put("key", "value", function(err, result) { context.put("key", valueBuffer, function(err, result) {
_error = _error || err; _error = _error || err;
context.get("key", function(err, result) { context.get("key", function(err, result) {
_error = _error || err; _error = _error || err;
@ -74,7 +85,7 @@ define(["IDBFS"], function(IDBFS) {
runs(function() { runs(function() {
expect(_error).toEqual(null); expect(_error).toEqual(null);
expect(_result).toEqual("value"); expect(_result).toEqual(valueBuffer);
}); });
}); });
@ -87,7 +98,7 @@ define(["IDBFS"], function(IDBFS) {
_error = err; _error = err;
var context = provider.getReadWriteContext(); var context = provider.getReadWriteContext();
context.put("key", "value", function(err, result) { context.put("key", valueBuffer, function(err, result) {
_error = _error || err; _error = _error || err;
context.delete("key", function(err, result) { context.delete("key", function(err, result) {
_error = _error || err; _error = _error || err;
@ -120,9 +131,9 @@ define(["IDBFS"], function(IDBFS) {
_error = err; _error = err;
var context = provider.getReadWriteContext(); var context = provider.getReadWriteContext();
context.put("key1", "value1", function(err, result) { context.put("key1", value1Buffer, function(err, result) {
_error = _error || err; _error = _error || err;
context.put("key2", "value2", function(err, result) { context.put("key2", value2Buffer, function(err, result) {
_error = _error || err; _error = _error || err;
context.clear(function(err) { context.clear(function(err) {
@ -164,7 +175,7 @@ define(["IDBFS"], function(IDBFS) {
_error = err; _error = err;
var context = provider.getReadOnlyContext(); var context = provider.getReadOnlyContext();
context.put("key1", "value1", function(err, result) { context.put("key1", value1Buffer, function(err, result) {
_error = _error || err; _error = _error || err;
_result = result; _result = result;
@ -185,8 +196,32 @@ define(["IDBFS"], function(IDBFS) {
}); });
} }
buildTestsFor('AES');
buildTestsFor('TripleDES'); // Encryption
buildTestsFor('Rabbit'); buildTestsFor('AES', function buildAdapter(provider) {
var passphrase = '' + Date.now();
return new IDBFS.FileSystem.adapters.AES(passphrase, provider);
});
buildTestsFor('TripleDES', function buildAdapter(provider) {
var passphrase = '' + Date.now();
return new IDBFS.FileSystem.adapters.TripleDES(passphrase, provider);
});
buildTestsFor('Rabbit', function buildAdapter(provider) {
var passphrase = '' + Date.now();
return new IDBFS.FileSystem.adapters.Rabbit(passphrase, provider);
});
// Compression
buildTestsFor('Zlib', function buildAdapter(provider) {
return new IDBFS.FileSystem.adapters.Zlib(provider);
});
// AES + Zlib together
buildTestsFor('AES+Zlib', function buildAdapter(provider) {
var passphrase = '' + Date.now();
var zlib = new IDBFS.FileSystem.adapters.Zlib(provider);
var AESwithZlib = new IDBFS.FileSystem.adapters.AES(passphrase, zlib);
return AESwithZlib;
});
}); });

View File

@ -19,5 +19,13 @@ define(["IDBFS"], function(IDBFS) {
it("has a default Encryption constructor", function() { it("has a default Encryption constructor", function() {
expect(typeof IDBFS.FileSystem.adapters.Encryption).toEqual('function'); expect(typeof IDBFS.FileSystem.adapters.Encryption).toEqual('function');
}); });
it("has a Zlib constructor", function() {
expect(typeof IDBFS.FileSystem.adapters.Zlib).toEqual('function');
});
it("has a default Compression constructor", function() {
expect(typeof IDBFS.FileSystem.adapters.Compression).toEqual('function');
});
}); });
}); });

View File

@ -36,7 +36,7 @@ define([
// IDBFS.FileSystem.adapters.* // IDBFS.FileSystem.adapters.*
"spec/adapters/adapters.spec", "spec/adapters/adapters.spec",
"spec/adapters/adapters.crypto.spec", "spec/adapters/adapters.general.spec",
// Ported node.js tests (filenames match names in https://github.com/joyent/node/tree/master/test) // Ported node.js tests (filenames match names in https://github.com/joyent/node/tree/master/test)
"spec/node-js/simple/test-fs-mkdir", "spec/node-js/simple/test-fs-mkdir",