mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-05 08:53:14 +00:00
[v2] modified repo create, file upload, update, download, ...
* repo create: myhome, pubrepo, group * handled 'is_password_set' etc. * view-online is not offered for file in enc repo in 'passwd local' mode * removed 'open local file' * added 'v2 tip' in seafile_access_check page
This commit is contained in:
BIN
media/img/client-v2-download-lib.png
Normal file
BIN
media/img/client-v2-download-lib.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
8
media/js/CryptoJS/components/lib-typedarrays-min.js
vendored
Normal file
8
media/js/CryptoJS/components/lib-typedarrays-min.js
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
CryptoJS v3.1.2
|
||||
code.google.com/p/crypto-js
|
||||
(c) 2009-2013 by Jeff Mott. All rights reserved.
|
||||
code.google.com/p/crypto-js/wiki/License
|
||||
*/
|
||||
(function(){if("function"==typeof ArrayBuffer){var b=CryptoJS.lib.WordArray,e=b.init;(b.init=function(a){a instanceof ArrayBuffer&&(a=new Uint8Array(a));if(a instanceof Int8Array||a instanceof Uint8ClampedArray||a instanceof Int16Array||a instanceof Uint16Array||a instanceof Int32Array||a instanceof Uint32Array||a instanceof Float32Array||a instanceof Float64Array)a=new Uint8Array(a.buffer,a.byteOffset,a.byteLength);if(a instanceof Uint8Array){for(var b=a.byteLength,d=[],c=0;c<b;c++)d[c>>>2]|=a[c]<<
|
||||
24-8*(c%4);e.call(this,d,b)}else e.apply(this,arguments)}).prototype=b}})();
|
35
media/js/CryptoJS/rollups/aes.js
Normal file
35
media/js/CryptoJS/rollups/aes.js
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
CryptoJS v3.1.2
|
||||
code.google.com/p/crypto-js
|
||||
(c) 2009-2013 by Jeff Mott. All rights reserved.
|
||||
code.google.com/p/crypto-js/wiki/License
|
||||
*/
|
||||
var CryptoJS=CryptoJS||function(u,p){var d={},l=d.lib={},s=function(){},t=l.Base={extend:function(a){s.prototype=this;var c=new s;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},
|
||||
r=l.WordArray=t.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=p?c:4*a.length},toString:function(a){return(a||v).stringify(this)},concat:function(a){var c=this.words,e=a.words,j=this.sigBytes;a=a.sigBytes;this.clamp();if(j%4)for(var k=0;k<a;k++)c[j+k>>>2]|=(e[k>>>2]>>>24-8*(k%4)&255)<<24-8*((j+k)%4);else if(65535<e.length)for(k=0;k<a;k+=4)c[j+k>>>2]=e[k>>>2];else c.push.apply(c,e);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<<
|
||||
32-8*(c%4);a.length=u.ceil(c/4)},clone:function(){var a=t.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],e=0;e<a;e+=4)c.push(4294967296*u.random()|0);return new r.init(c,a)}}),w=d.enc={},v=w.Hex={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j<a;j++){var k=c[j>>>2]>>>24-8*(j%4)&255;e.push((k>>>4).toString(16));e.push((k&15).toString(16))}return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j<c;j+=2)e[j>>>3]|=parseInt(a.substr(j,
|
||||
2),16)<<24-4*(j%8);return new r.init(e,c/2)}},b=w.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j<a;j++)e.push(String.fromCharCode(c[j>>>2]>>>24-8*(j%4)&255));return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j<c;j++)e[j>>>2]|=(a.charCodeAt(j)&255)<<24-8*(j%4);return new r.init(e,c)}},x=w.Utf8={stringify:function(a){try{return decodeURIComponent(escape(b.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return b.parse(unescape(encodeURIComponent(a)))}},
|
||||
q=l.BufferedBlockAlgorithm=t.extend({reset:function(){this._data=new r.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=x.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,e=c.words,j=c.sigBytes,k=this.blockSize,b=j/(4*k),b=a?u.ceil(b):u.max((b|0)-this._minBufferSize,0);a=b*k;j=u.min(4*a,j);if(a){for(var q=0;q<a;q+=k)this._doProcessBlock(e,q);q=e.splice(0,a);c.sigBytes-=j}return new r.init(q,j)},clone:function(){var a=t.clone.call(this);
|
||||
a._data=this._data.clone();return a},_minBufferSize:0});l.Hasher=q.extend({cfg:t.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){q.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(b,e){return(new a.init(e)).finalize(b)}},_createHmacHelper:function(a){return function(b,e){return(new n.HMAC.init(a,
|
||||
e)).finalize(b)}}});var n=d.algo={};return d}(Math);
|
||||
(function(){var u=CryptoJS,p=u.lib.WordArray;u.enc.Base64={stringify:function(d){var l=d.words,p=d.sigBytes,t=this._map;d.clamp();d=[];for(var r=0;r<p;r+=3)for(var w=(l[r>>>2]>>>24-8*(r%4)&255)<<16|(l[r+1>>>2]>>>24-8*((r+1)%4)&255)<<8|l[r+2>>>2]>>>24-8*((r+2)%4)&255,v=0;4>v&&r+0.75*v<p;v++)d.push(t.charAt(w>>>6*(3-v)&63));if(l=t.charAt(64))for(;d.length%4;)d.push(l);return d.join("")},parse:function(d){var l=d.length,s=this._map,t=s.charAt(64);t&&(t=d.indexOf(t),-1!=t&&(l=t));for(var t=[],r=0,w=0;w<
|
||||
l;w++)if(w%4){var v=s.indexOf(d.charAt(w-1))<<2*(w%4),b=s.indexOf(d.charAt(w))>>>6-2*(w%4);t[r>>>2]|=(v|b)<<24-8*(r%4);r++}return p.create(t,r)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})();
|
||||
(function(u){function p(b,n,a,c,e,j,k){b=b+(n&a|~n&c)+e+k;return(b<<j|b>>>32-j)+n}function d(b,n,a,c,e,j,k){b=b+(n&c|a&~c)+e+k;return(b<<j|b>>>32-j)+n}function l(b,n,a,c,e,j,k){b=b+(n^a^c)+e+k;return(b<<j|b>>>32-j)+n}function s(b,n,a,c,e,j,k){b=b+(a^(n|~c))+e+k;return(b<<j|b>>>32-j)+n}for(var t=CryptoJS,r=t.lib,w=r.WordArray,v=r.Hasher,r=t.algo,b=[],x=0;64>x;x++)b[x]=4294967296*u.abs(u.sin(x+1))|0;r=r.MD5=v.extend({_doReset:function(){this._hash=new w.init([1732584193,4023233417,2562383102,271733878])},
|
||||
_doProcessBlock:function(q,n){for(var a=0;16>a;a++){var c=n+a,e=q[c];q[c]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360}var a=this._hash.words,c=q[n+0],e=q[n+1],j=q[n+2],k=q[n+3],z=q[n+4],r=q[n+5],t=q[n+6],w=q[n+7],v=q[n+8],A=q[n+9],B=q[n+10],C=q[n+11],u=q[n+12],D=q[n+13],E=q[n+14],x=q[n+15],f=a[0],m=a[1],g=a[2],h=a[3],f=p(f,m,g,h,c,7,b[0]),h=p(h,f,m,g,e,12,b[1]),g=p(g,h,f,m,j,17,b[2]),m=p(m,g,h,f,k,22,b[3]),f=p(f,m,g,h,z,7,b[4]),h=p(h,f,m,g,r,12,b[5]),g=p(g,h,f,m,t,17,b[6]),m=p(m,g,h,f,w,22,b[7]),
|
||||
f=p(f,m,g,h,v,7,b[8]),h=p(h,f,m,g,A,12,b[9]),g=p(g,h,f,m,B,17,b[10]),m=p(m,g,h,f,C,22,b[11]),f=p(f,m,g,h,u,7,b[12]),h=p(h,f,m,g,D,12,b[13]),g=p(g,h,f,m,E,17,b[14]),m=p(m,g,h,f,x,22,b[15]),f=d(f,m,g,h,e,5,b[16]),h=d(h,f,m,g,t,9,b[17]),g=d(g,h,f,m,C,14,b[18]),m=d(m,g,h,f,c,20,b[19]),f=d(f,m,g,h,r,5,b[20]),h=d(h,f,m,g,B,9,b[21]),g=d(g,h,f,m,x,14,b[22]),m=d(m,g,h,f,z,20,b[23]),f=d(f,m,g,h,A,5,b[24]),h=d(h,f,m,g,E,9,b[25]),g=d(g,h,f,m,k,14,b[26]),m=d(m,g,h,f,v,20,b[27]),f=d(f,m,g,h,D,5,b[28]),h=d(h,f,
|
||||
m,g,j,9,b[29]),g=d(g,h,f,m,w,14,b[30]),m=d(m,g,h,f,u,20,b[31]),f=l(f,m,g,h,r,4,b[32]),h=l(h,f,m,g,v,11,b[33]),g=l(g,h,f,m,C,16,b[34]),m=l(m,g,h,f,E,23,b[35]),f=l(f,m,g,h,e,4,b[36]),h=l(h,f,m,g,z,11,b[37]),g=l(g,h,f,m,w,16,b[38]),m=l(m,g,h,f,B,23,b[39]),f=l(f,m,g,h,D,4,b[40]),h=l(h,f,m,g,c,11,b[41]),g=l(g,h,f,m,k,16,b[42]),m=l(m,g,h,f,t,23,b[43]),f=l(f,m,g,h,A,4,b[44]),h=l(h,f,m,g,u,11,b[45]),g=l(g,h,f,m,x,16,b[46]),m=l(m,g,h,f,j,23,b[47]),f=s(f,m,g,h,c,6,b[48]),h=s(h,f,m,g,w,10,b[49]),g=s(g,h,f,m,
|
||||
E,15,b[50]),m=s(m,g,h,f,r,21,b[51]),f=s(f,m,g,h,u,6,b[52]),h=s(h,f,m,g,k,10,b[53]),g=s(g,h,f,m,B,15,b[54]),m=s(m,g,h,f,e,21,b[55]),f=s(f,m,g,h,v,6,b[56]),h=s(h,f,m,g,x,10,b[57]),g=s(g,h,f,m,t,15,b[58]),m=s(m,g,h,f,D,21,b[59]),f=s(f,m,g,h,z,6,b[60]),h=s(h,f,m,g,C,10,b[61]),g=s(g,h,f,m,j,15,b[62]),m=s(m,g,h,f,A,21,b[63]);a[0]=a[0]+f|0;a[1]=a[1]+m|0;a[2]=a[2]+g|0;a[3]=a[3]+h|0},_doFinalize:function(){var b=this._data,n=b.words,a=8*this._nDataBytes,c=8*b.sigBytes;n[c>>>5]|=128<<24-c%32;var e=u.floor(a/
|
||||
4294967296);n[(c+64>>>9<<4)+15]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360;n[(c+64>>>9<<4)+14]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;b.sigBytes=4*(n.length+1);this._process();b=this._hash;n=b.words;for(a=0;4>a;a++)c=n[a],n[a]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360;return b},clone:function(){var b=v.clone.call(this);b._hash=this._hash.clone();return b}});t.MD5=v._createHelper(r);t.HmacMD5=v._createHmacHelper(r)})(Math);
|
||||
(function(){var u=CryptoJS,p=u.lib,d=p.Base,l=p.WordArray,p=u.algo,s=p.EvpKDF=d.extend({cfg:d.extend({keySize:4,hasher:p.MD5,iterations:1}),init:function(d){this.cfg=this.cfg.extend(d)},compute:function(d,r){for(var p=this.cfg,s=p.hasher.create(),b=l.create(),u=b.words,q=p.keySize,p=p.iterations;u.length<q;){n&&s.update(n);var n=s.update(d).finalize(r);s.reset();for(var a=1;a<p;a++)n=s.finalize(n),s.reset();b.concat(n)}b.sigBytes=4*q;return b}});u.EvpKDF=function(d,l,p){return s.create(p).compute(d,
|
||||
l)}})();
|
||||
CryptoJS.lib.Cipher||function(u){var p=CryptoJS,d=p.lib,l=d.Base,s=d.WordArray,t=d.BufferedBlockAlgorithm,r=p.enc.Base64,w=p.algo.EvpKDF,v=d.Cipher=t.extend({cfg:l.extend(),createEncryptor:function(e,a){return this.create(this._ENC_XFORM_MODE,e,a)},createDecryptor:function(e,a){return this.create(this._DEC_XFORM_MODE,e,a)},init:function(e,a,b){this.cfg=this.cfg.extend(b);this._xformMode=e;this._key=a;this.reset()},reset:function(){t.reset.call(this);this._doReset()},process:function(e){this._append(e);return this._process()},
|
||||
finalize:function(e){e&&this._append(e);return this._doFinalize()},keySize:4,ivSize:4,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:function(e){return{encrypt:function(b,k,d){return("string"==typeof k?c:a).encrypt(e,b,k,d)},decrypt:function(b,k,d){return("string"==typeof k?c:a).decrypt(e,b,k,d)}}}});d.StreamCipher=v.extend({_doFinalize:function(){return this._process(!0)},blockSize:1});var b=p.mode={},x=function(e,a,b){var c=this._iv;c?this._iv=u:c=this._prevBlock;for(var d=0;d<b;d++)e[a+d]^=
|
||||
c[d]},q=(d.BlockCipherMode=l.extend({createEncryptor:function(e,a){return this.Encryptor.create(e,a)},createDecryptor:function(e,a){return this.Decryptor.create(e,a)},init:function(e,a){this._cipher=e;this._iv=a}})).extend();q.Encryptor=q.extend({processBlock:function(e,a){var b=this._cipher,c=b.blockSize;x.call(this,e,a,c);b.encryptBlock(e,a);this._prevBlock=e.slice(a,a+c)}});q.Decryptor=q.extend({processBlock:function(e,a){var b=this._cipher,c=b.blockSize,d=e.slice(a,a+c);b.decryptBlock(e,a);x.call(this,
|
||||
e,a,c);this._prevBlock=d}});b=b.CBC=q;q=(p.pad={}).Pkcs7={pad:function(a,b){for(var c=4*b,c=c-a.sigBytes%c,d=c<<24|c<<16|c<<8|c,l=[],n=0;n<c;n+=4)l.push(d);c=s.create(l,c);a.concat(c)},unpad:function(a){a.sigBytes-=a.words[a.sigBytes-1>>>2]&255}};d.BlockCipher=v.extend({cfg:v.cfg.extend({mode:b,padding:q}),reset:function(){v.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var c=a.createEncryptor;else c=a.createDecryptor,this._minBufferSize=1;this._mode=c.call(a,
|
||||
this,b&&b.words)},_doProcessBlock:function(a,b){this._mode.processBlock(a,b)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var b=this._process(!0)}else b=this._process(!0),a.unpad(b);return b},blockSize:4});var n=d.CipherParams=l.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),b=(p.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a=a.salt;return(a?s.create([1398893684,
|
||||
1701076831]).concat(a).concat(b):b).toString(r)},parse:function(a){a=r.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var c=s.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return n.create({ciphertext:a,salt:c})}},a=d.SerializableCipher=l.extend({cfg:l.extend({format:b}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);var l=a.createEncryptor(c,d);b=l.finalize(b);l=l.cfg;return n.create({ciphertext:b,key:c,iv:l.iv,algorithm:a,mode:l.mode,padding:l.padding,blockSize:a.blockSize,formatter:d.format})},
|
||||
decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this._parse(b,d.format);return a.createDecryptor(c,d).finalize(b.ciphertext)},_parse:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),p=(p.kdf={}).OpenSSL={execute:function(a,b,c,d){d||(d=s.random(8));a=w.create({keySize:b+c}).compute(a,d);c=s.create(a.words.slice(b),4*c);a.sigBytes=4*b;return n.create({key:a,iv:c,salt:d})}},c=d.PasswordBasedCipher=a.extend({cfg:a.cfg.extend({kdf:p}),encrypt:function(b,c,d,l){l=this.cfg.extend(l);d=l.kdf.execute(d,
|
||||
b.keySize,b.ivSize);l.iv=d.iv;b=a.encrypt.call(this,b,c,d.key,l);b.mixIn(d);return b},decrypt:function(b,c,d,l){l=this.cfg.extend(l);c=this._parse(c,l.format);d=l.kdf.execute(d,b.keySize,b.ivSize,c.salt);l.iv=d.iv;return a.decrypt.call(this,b,c,d.key,l)}})}();
|
||||
(function(){for(var u=CryptoJS,p=u.lib.BlockCipher,d=u.algo,l=[],s=[],t=[],r=[],w=[],v=[],b=[],x=[],q=[],n=[],a=[],c=0;256>c;c++)a[c]=128>c?c<<1:c<<1^283;for(var e=0,j=0,c=0;256>c;c++){var k=j^j<<1^j<<2^j<<3^j<<4,k=k>>>8^k&255^99;l[e]=k;s[k]=e;var z=a[e],F=a[z],G=a[F],y=257*a[k]^16843008*k;t[e]=y<<24|y>>>8;r[e]=y<<16|y>>>16;w[e]=y<<8|y>>>24;v[e]=y;y=16843009*G^65537*F^257*z^16843008*e;b[k]=y<<24|y>>>8;x[k]=y<<16|y>>>16;q[k]=y<<8|y>>>24;n[k]=y;e?(e=z^a[a[a[G^z]]],j^=a[a[j]]):e=j=1}var H=[0,1,2,4,8,
|
||||
16,32,64,128,27,54],d=d.AES=p.extend({_doReset:function(){for(var a=this._key,c=a.words,d=a.sigBytes/4,a=4*((this._nRounds=d+6)+1),e=this._keySchedule=[],j=0;j<a;j++)if(j<d)e[j]=c[j];else{var k=e[j-1];j%d?6<d&&4==j%d&&(k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255]):(k=k<<8|k>>>24,k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255],k^=H[j/d|0]<<24);e[j]=e[j-d]^k}c=this._invKeySchedule=[];for(d=0;d<a;d++)j=a-d,k=d%4?e[j]:e[j-4],c[d]=4>d||4>=j?k:b[l[k>>>24]]^x[l[k>>>16&255]]^q[l[k>>>
|
||||
8&255]]^n[l[k&255]]},encryptBlock:function(a,b){this._doCryptBlock(a,b,this._keySchedule,t,r,w,v,l)},decryptBlock:function(a,c){var d=a[c+1];a[c+1]=a[c+3];a[c+3]=d;this._doCryptBlock(a,c,this._invKeySchedule,b,x,q,n,s);d=a[c+1];a[c+1]=a[c+3];a[c+3]=d},_doCryptBlock:function(a,b,c,d,e,j,l,f){for(var m=this._nRounds,g=a[b]^c[0],h=a[b+1]^c[1],k=a[b+2]^c[2],n=a[b+3]^c[3],p=4,r=1;r<m;r++)var q=d[g>>>24]^e[h>>>16&255]^j[k>>>8&255]^l[n&255]^c[p++],s=d[h>>>24]^e[k>>>16&255]^j[n>>>8&255]^l[g&255]^c[p++],t=
|
||||
d[k>>>24]^e[n>>>16&255]^j[g>>>8&255]^l[h&255]^c[p++],n=d[n>>>24]^e[g>>>16&255]^j[h>>>8&255]^l[k&255]^c[p++],g=q,h=s,k=t;q=(f[g>>>24]<<24|f[h>>>16&255]<<16|f[k>>>8&255]<<8|f[n&255])^c[p++];s=(f[h>>>24]<<24|f[k>>>16&255]<<16|f[n>>>8&255]<<8|f[g&255])^c[p++];t=(f[k>>>24]<<24|f[n>>>16&255]<<16|f[g>>>8&255]<<8|f[h&255])^c[p++];n=(f[n>>>24]<<24|f[g>>>16&255]<<16|f[h>>>8&255]<<8|f[k&255])^c[p++];a[b]=q;a[b+1]=s;a[b+2]=t;a[b+3]=n},keySize:8});u.AES=p._createHelper(d)})();
|
15
media/js/CryptoJS/rollups/sha1.js
Normal file
15
media/js/CryptoJS/rollups/sha1.js
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
CryptoJS v3.1.2
|
||||
code.google.com/p/crypto-js
|
||||
(c) 2009-2013 by Jeff Mott. All rights reserved.
|
||||
code.google.com/p/crypto-js/wiki/License
|
||||
*/
|
||||
var CryptoJS=CryptoJS||function(e,m){var p={},j=p.lib={},l=function(){},f=j.Base={extend:function(a){l.prototype=this;var c=new l;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},
|
||||
n=j.WordArray=f.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=m?c:4*a.length},toString:function(a){return(a||h).stringify(this)},concat:function(a){var c=this.words,q=a.words,d=this.sigBytes;a=a.sigBytes;this.clamp();if(d%4)for(var b=0;b<a;b++)c[d+b>>>2]|=(q[b>>>2]>>>24-8*(b%4)&255)<<24-8*((d+b)%4);else if(65535<q.length)for(b=0;b<a;b+=4)c[d+b>>>2]=q[b>>>2];else c.push.apply(c,q);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<<
|
||||
32-8*(c%4);a.length=e.ceil(c/4)},clone:function(){var a=f.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],b=0;b<a;b+=4)c.push(4294967296*e.random()|0);return new n.init(c,a)}}),b=p.enc={},h=b.Hex={stringify:function(a){var c=a.words;a=a.sigBytes;for(var b=[],d=0;d<a;d++){var f=c[d>>>2]>>>24-8*(d%4)&255;b.push((f>>>4).toString(16));b.push((f&15).toString(16))}return b.join("")},parse:function(a){for(var c=a.length,b=[],d=0;d<c;d+=2)b[d>>>3]|=parseInt(a.substr(d,
|
||||
2),16)<<24-4*(d%8);return new n.init(b,c/2)}},g=b.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var b=[],d=0;d<a;d++)b.push(String.fromCharCode(c[d>>>2]>>>24-8*(d%4)&255));return b.join("")},parse:function(a){for(var c=a.length,b=[],d=0;d<c;d++)b[d>>>2]|=(a.charCodeAt(d)&255)<<24-8*(d%4);return new n.init(b,c)}},r=b.Utf8={stringify:function(a){try{return decodeURIComponent(escape(g.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return g.parse(unescape(encodeURIComponent(a)))}},
|
||||
k=j.BufferedBlockAlgorithm=f.extend({reset:function(){this._data=new n.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=r.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,b=c.words,d=c.sigBytes,f=this.blockSize,h=d/(4*f),h=a?e.ceil(h):e.max((h|0)-this._minBufferSize,0);a=h*f;d=e.min(4*a,d);if(a){for(var g=0;g<a;g+=f)this._doProcessBlock(b,g);g=b.splice(0,a);c.sigBytes-=d}return new n.init(g,d)},clone:function(){var a=f.clone.call(this);
|
||||
a._data=this._data.clone();return a},_minBufferSize:0});j.Hasher=k.extend({cfg:f.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){k.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(c,b){return(new a.init(b)).finalize(c)}},_createHmacHelper:function(a){return function(b,f){return(new s.HMAC.init(a,
|
||||
f)).finalize(b)}}});var s=p.algo={};return p}(Math);
|
||||
(function(){var e=CryptoJS,m=e.lib,p=m.WordArray,j=m.Hasher,l=[],m=e.algo.SHA1=j.extend({_doReset:function(){this._hash=new p.init([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(f,n){for(var b=this._hash.words,h=b[0],g=b[1],e=b[2],k=b[3],j=b[4],a=0;80>a;a++){if(16>a)l[a]=f[n+a]|0;else{var c=l[a-3]^l[a-8]^l[a-14]^l[a-16];l[a]=c<<1|c>>>31}c=(h<<5|h>>>27)+j+l[a];c=20>a?c+((g&e|~g&k)+1518500249):40>a?c+((g^e^k)+1859775393):60>a?c+((g&e|g&k|e&k)-1894007588):c+((g^e^
|
||||
k)-899497514);j=k;k=e;e=g<<30|g>>>2;g=h;h=c}b[0]=b[0]+h|0;b[1]=b[1]+g|0;b[2]=b[2]+e|0;b[3]=b[3]+k|0;b[4]=b[4]+j|0},_doFinalize:function(){var f=this._data,e=f.words,b=8*this._nDataBytes,h=8*f.sigBytes;e[h>>>5]|=128<<24-h%32;e[(h+64>>>9<<4)+14]=Math.floor(b/4294967296);e[(h+64>>>9<<4)+15]=b;f.sigBytes=4*e.length;this._process();return this._hash},clone:function(){var e=j.clone.call(this);e._hash=this._hash.clone();return e}});e.SHA1=j._createHelper(m);e.HmacSHA1=j._createHmacHelper(m)})();
|
@@ -54,6 +54,12 @@ $(document).click(function(e) {
|
||||
}
|
||||
});
|
||||
|
||||
// clear repo enc info when log out
|
||||
$('#logout').click(function() {
|
||||
if ('localStorage' in window && window['localStorage'] !== null) {
|
||||
localStorage.clear();
|
||||
}
|
||||
});
|
||||
if ($.browser.mozilla || $.browser.msie) {
|
||||
$('a').focus(function() {
|
||||
$(this).blur();
|
||||
|
37
media/js/codecBytes.js
Normal file
37
media/js/codecBytes.js
Normal file
@@ -0,0 +1,37 @@
|
||||
/** @fileOverview Bit array codec implementations.
|
||||
*
|
||||
* @author Emily Stark
|
||||
* @author Mike Hamburg
|
||||
* @author Dan Boneh
|
||||
*/
|
||||
|
||||
/** @namespace Arrays of bytes */
|
||||
sjcl.codec.bytes = {
|
||||
/** Convert from a bitArray to an array of bytes. */
|
||||
fromBits: function (arr) {
|
||||
var out = [], bl = sjcl.bitArray.bitLength(arr), i, tmp;
|
||||
for (i=0; i<bl/8; i++) {
|
||||
if ((i&3) === 0) {
|
||||
tmp = arr[i/4];
|
||||
}
|
||||
out.push(tmp >>> 24);
|
||||
tmp <<= 8;
|
||||
}
|
||||
return out;
|
||||
},
|
||||
/** Convert from an array of bytes to a bitArray. */
|
||||
toBits: function (bytes) {
|
||||
var out = [], i, tmp=0;
|
||||
for (i=0; i<bytes.length; i++) {
|
||||
tmp = tmp << 8 | bytes[i];
|
||||
if ((i&3) === 3) {
|
||||
out.push(tmp);
|
||||
tmp = 0;
|
||||
}
|
||||
}
|
||||
if (i&3) {
|
||||
out.push(sjcl.bitArray.partial(8*(i&3), tmp));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
};
|
43
media/js/file_crypto.js
Normal file
43
media/js/file_crypto.js
Normal file
@@ -0,0 +1,43 @@
|
||||
importScripts('CryptoJS/rollups/aes.js');
|
||||
importScripts('CryptoJS/rollups/sha1.js');
|
||||
importScripts('CryptoJS/components/lib-typedarrays-min.js');
|
||||
|
||||
self.onmessage = function (e) {
|
||||
if (e.data.encrypt) {
|
||||
encrypt(e);
|
||||
} else {
|
||||
decrypt(e);
|
||||
}
|
||||
}
|
||||
|
||||
function encrypt(e) {
|
||||
var encrypted = {index: e.data.index};
|
||||
var fReader = new FileReaderSync();
|
||||
var block = fReader.readAsArrayBuffer(e.data.block),
|
||||
key = e.data.key,
|
||||
iv = e.data.iv;
|
||||
|
||||
try {
|
||||
var enc_obj = CryptoJS.AES.encrypt(CryptoJS.lib.WordArray.create(block), CryptoJS.enc.Hex.parse(key), {iv: CryptoJS.enc.Hex.parse(iv)});
|
||||
encrypted.block = enc_obj.ciphertext;
|
||||
encrypted.block_id = CryptoJS.SHA1(enc_obj.ciphertext).toString(CryptoJS.enc.Hex);
|
||||
postMessage(encrypted);
|
||||
} catch (e){
|
||||
postMessage("Error");
|
||||
}
|
||||
}
|
||||
|
||||
function decrypt(e) {
|
||||
var decrypted = {index: e.data.index};
|
||||
var block = e.data.block,
|
||||
key = e.data.key,
|
||||
iv = e.data.iv;
|
||||
|
||||
try {
|
||||
var d_block = CryptoJS.AES.decrypt(CryptoJS.lib.WordArray.create(block).toString(CryptoJS.enc.Base64), CryptoJS.enc.Hex.parse(key), {iv: CryptoJS.enc.Hex.parse(iv)});
|
||||
decrypted.block = d_block;
|
||||
postMessage(decrypted);
|
||||
} catch (e){
|
||||
postMessage("Error");
|
||||
}
|
||||
}
|
48
media/js/sjcl.min.js
vendored
Normal file
48
media/js/sjcl.min.js
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
"use strict";function q(a){throw a;}var t=void 0,u=!1;var sjcl={cipher:{},hash:{},keyexchange:{},mode:{},misc:{},codec:{},exception:{corrupt:function(a){this.toString=function(){return"CORRUPT: "+this.message};this.message=a},invalid:function(a){this.toString=function(){return"INVALID: "+this.message};this.message=a},bug:function(a){this.toString=function(){return"BUG: "+this.message};this.message=a},notReady:function(a){this.toString=function(){return"NOT READY: "+this.message};this.message=a}}};
|
||||
"undefined"!=typeof module&&module.exports&&(module.exports=sjcl);
|
||||
sjcl.cipher.aes=function(a){this.j[0][0][0]||this.D();var b,c,d,e,f=this.j[0][4],g=this.j[1];b=a.length;var h=1;4!==b&&(6!==b&&8!==b)&&q(new sjcl.exception.invalid("invalid aes key size"));this.a=[d=a.slice(0),e=[]];for(a=b;a<4*b+28;a++){c=d[a-1];if(0===a%b||8===b&&4===a%b)c=f[c>>>24]<<24^f[c>>16&255]<<16^f[c>>8&255]<<8^f[c&255],0===a%b&&(c=c<<8^c>>>24^h<<24,h=h<<1^283*(h>>7));d[a]=d[a-b]^c}for(b=0;a;b++,a--)c=d[b&3?a:a-4],e[b]=4>=a||4>b?c:g[0][f[c>>>24]]^g[1][f[c>>16&255]]^g[2][f[c>>8&255]]^g[3][f[c&
|
||||
255]]};
|
||||
sjcl.cipher.aes.prototype={encrypt:function(a){return y(this,a,0)},decrypt:function(a){return y(this,a,1)},j:[[[],[],[],[],[]],[[],[],[],[],[]]],D:function(){var a=this.j[0],b=this.j[1],c=a[4],d=b[4],e,f,g,h=[],l=[],k,n,m,p;for(e=0;0x100>e;e++)l[(h[e]=e<<1^283*(e>>7))^e]=e;for(f=g=0;!c[f];f^=k||1,g=l[g]||1){m=g^g<<1^g<<2^g<<3^g<<4;m=m>>8^m&255^99;c[f]=m;d[m]=f;n=h[e=h[k=h[f]]];p=0x1010101*n^0x10001*e^0x101*k^0x1010100*f;n=0x101*h[m]^0x1010100*m;for(e=0;4>e;e++)a[e][f]=n=n<<24^n>>>8,b[e][m]=p=p<<24^p>>>8}for(e=
|
||||
0;5>e;e++)a[e]=a[e].slice(0),b[e]=b[e].slice(0)}};
|
||||
function y(a,b,c){4!==b.length&&q(new sjcl.exception.invalid("invalid aes block size"));var d=a.a[c],e=b[0]^d[0],f=b[c?3:1]^d[1],g=b[2]^d[2];b=b[c?1:3]^d[3];var h,l,k,n=d.length/4-2,m,p=4,s=[0,0,0,0];h=a.j[c];a=h[0];var r=h[1],v=h[2],w=h[3],x=h[4];for(m=0;m<n;m++)h=a[e>>>24]^r[f>>16&255]^v[g>>8&255]^w[b&255]^d[p],l=a[f>>>24]^r[g>>16&255]^v[b>>8&255]^w[e&255]^d[p+1],k=a[g>>>24]^r[b>>16&255]^v[e>>8&255]^w[f&255]^d[p+2],b=a[b>>>24]^r[e>>16&255]^v[f>>8&255]^w[g&255]^d[p+3],p+=4,e=h,f=l,g=k;for(m=0;4>
|
||||
m;m++)s[c?3&-m:m]=x[e>>>24]<<24^x[f>>16&255]<<16^x[g>>8&255]<<8^x[b&255]^d[p++],h=e,e=f,f=g,g=b,b=h;return s}
|
||||
sjcl.bitArray={bitSlice:function(a,b,c){a=sjcl.bitArray.O(a.slice(b/32),32-(b&31)).slice(1);return c===t?a:sjcl.bitArray.clamp(a,c-b)},extract:function(a,b,c){var d=Math.floor(-b-c&31);return((b+c-1^b)&-32?a[b/32|0]<<32-d^a[b/32+1|0]>>>d:a[b/32|0]>>>d)&(1<<c)-1},concat:function(a,b){if(0===a.length||0===b.length)return a.concat(b);var c=a[a.length-1],d=sjcl.bitArray.getPartial(c);return 32===d?a.concat(b):sjcl.bitArray.O(b,d,c|0,a.slice(0,a.length-1))},bitLength:function(a){var b=a.length;return 0===
|
||||
b?0:32*(b-1)+sjcl.bitArray.getPartial(a[b-1])},clamp:function(a,b){if(32*a.length<b)return a;a=a.slice(0,Math.ceil(b/32));var c=a.length;b&=31;0<c&&b&&(a[c-1]=sjcl.bitArray.partial(b,a[c-1]&2147483648>>b-1,1));return a},partial:function(a,b,c){return 32===a?b:(c?b|0:b<<32-a)+0x10000000000*a},getPartial:function(a){return Math.round(a/0x10000000000)||32},equal:function(a,b){if(sjcl.bitArray.bitLength(a)!==sjcl.bitArray.bitLength(b))return u;var c=0,d;for(d=0;d<a.length;d++)c|=a[d]^b[d];return 0===
|
||||
c},O:function(a,b,c,d){var e;e=0;for(d===t&&(d=[]);32<=b;b-=32)d.push(c),c=0;if(0===b)return d.concat(a);for(e=0;e<a.length;e++)d.push(c|a[e]>>>b),c=a[e]<<32-b;e=a.length?a[a.length-1]:0;a=sjcl.bitArray.getPartial(e);d.push(sjcl.bitArray.partial(b+a&31,32<b+a?c:d.pop(),1));return d},k:function(a,b){return[a[0]^b[0],a[1]^b[1],a[2]^b[2],a[3]^b[3]]}};
|
||||
sjcl.codec.utf8String={fromBits:function(a){var b="",c=sjcl.bitArray.bitLength(a),d,e;for(d=0;d<c/8;d++)0===(d&3)&&(e=a[d/4]),b+=String.fromCharCode(e>>>24),e<<=8;return decodeURIComponent(escape(b))},toBits:function(a){a=unescape(encodeURIComponent(a));var b=[],c,d=0;for(c=0;c<a.length;c++)d=d<<8|a.charCodeAt(c),3===(c&3)&&(b.push(d),d=0);c&3&&b.push(sjcl.bitArray.partial(8*(c&3),d));return b}};
|
||||
sjcl.codec.hex={fromBits:function(a){var b="",c;for(c=0;c<a.length;c++)b+=((a[c]|0)+0xf00000000000).toString(16).substr(4);return b.substr(0,sjcl.bitArray.bitLength(a)/4)},toBits:function(a){var b,c=[],d;a=a.replace(/\s|0x/g,"");d=a.length;a+="00000000";for(b=0;b<a.length;b+=8)c.push(parseInt(a.substr(b,8),16)^0);return sjcl.bitArray.clamp(c,4*d)}};
|
||||
sjcl.codec.base64={I:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",fromBits:function(a,b,c){var d="",e=0,f=sjcl.codec.base64.I,g=0,h=sjcl.bitArray.bitLength(a);c&&(f=f.substr(0,62)+"-_");for(c=0;6*d.length<h;)d+=f.charAt((g^a[c]>>>e)>>>26),6>e?(g=a[c]<<6-e,e+=26,c++):(g<<=6,e-=6);for(;d.length&3&&!b;)d+="=";return d},toBits:function(a,b){a=a.replace(/\s|=/g,"");var c=[],d,e=0,f=sjcl.codec.base64.I,g=0,h;b&&(f=f.substr(0,62)+"-_");for(d=0;d<a.length;d++)h=f.indexOf(a.charAt(d)),
|
||||
0>h&&q(new sjcl.exception.invalid("this isn't base64!")),26<e?(e-=26,c.push(g^h>>>e),g=h<<32-e):(e+=6,g^=h<<32-e);e&56&&c.push(sjcl.bitArray.partial(e&56,g,1));return c}};sjcl.codec.base64url={fromBits:function(a){return sjcl.codec.base64.fromBits(a,1,1)},toBits:function(a){return sjcl.codec.base64.toBits(a,1)}};sjcl.hash.sha256=function(a){this.a[0]||this.D();a?(this.q=a.q.slice(0),this.m=a.m.slice(0),this.g=a.g):this.reset()};sjcl.hash.sha256.hash=function(a){return(new sjcl.hash.sha256).update(a).finalize()};
|
||||
sjcl.hash.sha256.prototype={blockSize:512,reset:function(){this.q=this.M.slice(0);this.m=[];this.g=0;return this},update:function(a){"string"===typeof a&&(a=sjcl.codec.utf8String.toBits(a));var b,c=this.m=sjcl.bitArray.concat(this.m,a);b=this.g;a=this.g=b+sjcl.bitArray.bitLength(a);for(b=512+b&-512;b<=a;b+=512)z(this,c.splice(0,16));return this},finalize:function(){var a,b=this.m,c=this.q,b=sjcl.bitArray.concat(b,[sjcl.bitArray.partial(1,1)]);for(a=b.length+2;a&15;a++)b.push(0);b.push(Math.floor(this.g/
|
||||
4294967296));for(b.push(this.g|0);b.length;)z(this,b.splice(0,16));this.reset();return c},M:[],a:[],D:function(){function a(a){return 0x100000000*(a-Math.floor(a))|0}var b=0,c=2,d;a:for(;64>b;c++){for(d=2;d*d<=c;d++)if(0===c%d)continue a;8>b&&(this.M[b]=a(Math.pow(c,0.5)));this.a[b]=a(Math.pow(c,1/3));b++}}};
|
||||
function z(a,b){var c,d,e,f=b.slice(0),g=a.q,h=a.a,l=g[0],k=g[1],n=g[2],m=g[3],p=g[4],s=g[5],r=g[6],v=g[7];for(c=0;64>c;c++)16>c?d=f[c]:(d=f[c+1&15],e=f[c+14&15],d=f[c&15]=(d>>>7^d>>>18^d>>>3^d<<25^d<<14)+(e>>>17^e>>>19^e>>>10^e<<15^e<<13)+f[c&15]+f[c+9&15]|0),d=d+v+(p>>>6^p>>>11^p>>>25^p<<26^p<<21^p<<7)+(r^p&(s^r))+h[c],v=r,r=s,s=p,p=m+d|0,m=n,n=k,k=l,l=d+(k&n^m&(k^n))+(k>>>2^k>>>13^k>>>22^k<<30^k<<19^k<<10)|0;g[0]=g[0]+l|0;g[1]=g[1]+k|0;g[2]=g[2]+n|0;g[3]=g[3]+m|0;g[4]=g[4]+p|0;g[5]=g[5]+s|0;g[6]=
|
||||
g[6]+r|0;g[7]=g[7]+v|0}
|
||||
sjcl.mode.ccm={name:"ccm",encrypt:function(a,b,c,d,e){var f,g=b.slice(0),h=sjcl.bitArray,l=h.bitLength(c)/8,k=h.bitLength(g)/8;e=e||64;d=d||[];7>l&&q(new sjcl.exception.invalid("ccm: iv must be at least 7 bytes"));for(f=2;4>f&&k>>>8*f;f++);f<15-l&&(f=15-l);c=h.clamp(c,8*(15-f));b=sjcl.mode.ccm.K(a,b,c,d,e,f);g=sjcl.mode.ccm.n(a,g,c,b,e,f);return h.concat(g.data,g.tag)},decrypt:function(a,b,c,d,e){e=e||64;d=d||[];var f=sjcl.bitArray,g=f.bitLength(c)/8,h=f.bitLength(b),l=f.clamp(b,h-e),k=f.bitSlice(b,
|
||||
h-e),h=(h-e)/8;7>g&&q(new sjcl.exception.invalid("ccm: iv must be at least 7 bytes"));for(b=2;4>b&&h>>>8*b;b++);b<15-g&&(b=15-g);c=f.clamp(c,8*(15-b));l=sjcl.mode.ccm.n(a,l,c,k,e,b);a=sjcl.mode.ccm.K(a,l.data,c,d,e,b);f.equal(l.tag,a)||q(new sjcl.exception.corrupt("ccm: tag doesn't match"));return l.data},K:function(a,b,c,d,e,f){var g=[],h=sjcl.bitArray,l=h.k;e/=8;(e%2||4>e||16<e)&&q(new sjcl.exception.invalid("ccm: invalid tag length"));(0xffffffff<d.length||0xffffffff<b.length)&&q(new sjcl.exception.bug("ccm: can't deal with 4GiB or more data"));
|
||||
f=[h.partial(8,(d.length?64:0)|e-2<<2|f-1)];f=h.concat(f,c);f[3]|=h.bitLength(b)/8;f=a.encrypt(f);if(d.length){c=h.bitLength(d)/8;65279>=c?g=[h.partial(16,c)]:0xffffffff>=c&&(g=h.concat([h.partial(16,65534)],[c]));g=h.concat(g,d);for(d=0;d<g.length;d+=4)f=a.encrypt(l(f,g.slice(d,d+4).concat([0,0,0])))}for(d=0;d<b.length;d+=4)f=a.encrypt(l(f,b.slice(d,d+4).concat([0,0,0])));return h.clamp(f,8*e)},n:function(a,b,c,d,e,f){var g,h=sjcl.bitArray;g=h.k;var l=b.length,k=h.bitLength(b);c=h.concat([h.partial(8,
|
||||
f-1)],c).concat([0,0,0]).slice(0,4);d=h.bitSlice(g(d,a.encrypt(c)),0,e);if(!l)return{tag:d,data:[]};for(g=0;g<l;g+=4)c[3]++,e=a.encrypt(c),b[g]^=e[0],b[g+1]^=e[1],b[g+2]^=e[2],b[g+3]^=e[3];return{tag:d,data:h.clamp(b,k)}}};
|
||||
sjcl.mode.ocb2={name:"ocb2",encrypt:function(a,b,c,d,e,f){128!==sjcl.bitArray.bitLength(c)&&q(new sjcl.exception.invalid("ocb iv must be 128 bits"));var g,h=sjcl.mode.ocb2.G,l=sjcl.bitArray,k=l.k,n=[0,0,0,0];c=h(a.encrypt(c));var m,p=[];d=d||[];e=e||64;for(g=0;g+4<b.length;g+=4)m=b.slice(g,g+4),n=k(n,m),p=p.concat(k(c,a.encrypt(k(c,m)))),c=h(c);m=b.slice(g);b=l.bitLength(m);g=a.encrypt(k(c,[0,0,0,b]));m=l.clamp(k(m.concat([0,0,0]),g),b);n=k(n,k(m.concat([0,0,0]),g));n=a.encrypt(k(n,k(c,h(c))));d.length&&
|
||||
(n=k(n,f?d:sjcl.mode.ocb2.pmac(a,d)));return p.concat(l.concat(m,l.clamp(n,e)))},decrypt:function(a,b,c,d,e,f){128!==sjcl.bitArray.bitLength(c)&&q(new sjcl.exception.invalid("ocb iv must be 128 bits"));e=e||64;var g=sjcl.mode.ocb2.G,h=sjcl.bitArray,l=h.k,k=[0,0,0,0],n=g(a.encrypt(c)),m,p,s=sjcl.bitArray.bitLength(b)-e,r=[];d=d||[];for(c=0;c+4<s/32;c+=4)m=l(n,a.decrypt(l(n,b.slice(c,c+4)))),k=l(k,m),r=r.concat(m),n=g(n);p=s-32*c;m=a.encrypt(l(n,[0,0,0,p]));m=l(m,h.clamp(b.slice(c),p).concat([0,0,0]));
|
||||
k=l(k,m);k=a.encrypt(l(k,l(n,g(n))));d.length&&(k=l(k,f?d:sjcl.mode.ocb2.pmac(a,d)));h.equal(h.clamp(k,e),h.bitSlice(b,s))||q(new sjcl.exception.corrupt("ocb: tag doesn't match"));return r.concat(h.clamp(m,p))},pmac:function(a,b){var c,d=sjcl.mode.ocb2.G,e=sjcl.bitArray,f=e.k,g=[0,0,0,0],h=a.encrypt([0,0,0,0]),h=f(h,d(d(h)));for(c=0;c+4<b.length;c+=4)h=d(h),g=f(g,a.encrypt(f(h,b.slice(c,c+4))));c=b.slice(c);128>e.bitLength(c)&&(h=f(h,d(h)),c=e.concat(c,[-2147483648,0,0,0]));g=f(g,c);return a.encrypt(f(d(f(h,
|
||||
d(h))),g))},G:function(a){return[a[0]<<1^a[1]>>>31,a[1]<<1^a[2]>>>31,a[2]<<1^a[3]>>>31,a[3]<<1^135*(a[0]>>>31)]}};
|
||||
sjcl.mode.gcm={name:"gcm",encrypt:function(a,b,c,d,e){var f=b.slice(0);b=sjcl.bitArray;d=d||[];a=sjcl.mode.gcm.n(!0,a,f,d,c,e||128);return b.concat(a.data,a.tag)},decrypt:function(a,b,c,d,e){var f=b.slice(0),g=sjcl.bitArray,h=g.bitLength(f);e=e||128;d=d||[];e<=h?(b=g.bitSlice(f,h-e),f=g.bitSlice(f,0,h-e)):(b=f,f=[]);a=sjcl.mode.gcm.n(u,a,f,d,c,e);g.equal(a.tag,b)||q(new sjcl.exception.corrupt("gcm: tag doesn't match"));return a.data},U:function(a,b){var c,d,e,f,g,h=sjcl.bitArray.k;e=[0,0,0,0];f=b.slice(0);
|
||||
for(c=0;128>c;c++){(d=0!==(a[Math.floor(c/32)]&1<<31-c%32))&&(e=h(e,f));g=0!==(f[3]&1);for(d=3;0<d;d--)f[d]=f[d]>>>1|(f[d-1]&1)<<31;f[0]>>>=1;g&&(f[0]^=-0x1f000000)}return e},f:function(a,b,c){var d,e=c.length;b=b.slice(0);for(d=0;d<e;d+=4)b[0]^=0xffffffff&c[d],b[1]^=0xffffffff&c[d+1],b[2]^=0xffffffff&c[d+2],b[3]^=0xffffffff&c[d+3],b=sjcl.mode.gcm.U(b,a);return b},n:function(a,b,c,d,e,f){var g,h,l,k,n,m,p,s,r=sjcl.bitArray;m=c.length;p=r.bitLength(c);s=r.bitLength(d);h=r.bitLength(e);g=b.encrypt([0,
|
||||
0,0,0]);96===h?(e=e.slice(0),e=r.concat(e,[1])):(e=sjcl.mode.gcm.f(g,[0,0,0,0],e),e=sjcl.mode.gcm.f(g,e,[0,0,Math.floor(h/0x100000000),h&0xffffffff]));h=sjcl.mode.gcm.f(g,[0,0,0,0],d);n=e.slice(0);d=h.slice(0);a||(d=sjcl.mode.gcm.f(g,h,c));for(k=0;k<m;k+=4)n[3]++,l=b.encrypt(n),c[k]^=l[0],c[k+1]^=l[1],c[k+2]^=l[2],c[k+3]^=l[3];c=r.clamp(c,p);a&&(d=sjcl.mode.gcm.f(g,h,c));a=[Math.floor(s/0x100000000),s&0xffffffff,Math.floor(p/0x100000000),p&0xffffffff];d=sjcl.mode.gcm.f(g,d,a);l=b.encrypt(e);d[0]^=l[0];
|
||||
d[1]^=l[1];d[2]^=l[2];d[3]^=l[3];return{tag:r.bitSlice(d,0,f),data:c}}};sjcl.misc.hmac=function(a,b){this.L=b=b||sjcl.hash.sha256;var c=[[],[]],d,e=b.prototype.blockSize/32;this.o=[new b,new b];a.length>e&&(a=b.hash(a));for(d=0;d<e;d++)c[0][d]=a[d]^909522486,c[1][d]=a[d]^1549556828;this.o[0].update(c[0]);this.o[1].update(c[1])};sjcl.misc.hmac.prototype.encrypt=sjcl.misc.hmac.prototype.mac=function(a){a=(new this.L(this.o[0])).update(a).finalize();return(new this.L(this.o[1])).update(a).finalize()};
|
||||
sjcl.misc.pbkdf2=function(a,b,c,d,e){c=c||1E3;(0>d||0>c)&&q(sjcl.exception.invalid("invalid params to pbkdf2"));"string"===typeof a&&(a=sjcl.codec.utf8String.toBits(a));e=e||sjcl.misc.hmac;a=new e(a);var f,g,h,l,k=[],n=sjcl.bitArray;for(l=1;32*k.length<(d||1);l++){e=f=a.encrypt(n.concat(b,[l]));for(g=1;g<c;g++){f=a.encrypt(f);for(h=0;h<f.length;h++)e[h]^=f[h]}k=k.concat(e)}d&&(k=n.clamp(k,d));return k};
|
||||
sjcl.prng=function(a){this.b=[new sjcl.hash.sha256];this.h=[0];this.F=0;this.t={};this.C=0;this.J={};this.N=this.c=this.i=this.T=0;this.a=[0,0,0,0,0,0,0,0];this.e=[0,0,0,0];this.A=t;this.B=a;this.p=u;this.z={progress:{},seeded:{}};this.l=this.S=0;this.u=1;this.w=2;this.Q=0x10000;this.H=[0,48,64,96,128,192,0x100,384,512,768,1024];this.R=3E4;this.P=80};
|
||||
sjcl.prng.prototype={randomWords:function(a,b){var c=[],d;d=this.isReady(b);var e;d===this.l&&q(new sjcl.exception.notReady("generator isn't seeded"));if(d&this.w){d=!(d&this.u);e=[];var f=0,g;this.N=e[0]=(new Date).valueOf()+this.R;for(g=0;16>g;g++)e.push(0x100000000*Math.random()|0);for(g=0;g<this.b.length&&!(e=e.concat(this.b[g].finalize()),f+=this.h[g],this.h[g]=0,!d&&this.F&1<<g);g++);this.F>=1<<this.b.length&&(this.b.push(new sjcl.hash.sha256),this.h.push(0));this.c-=f;f>this.i&&(this.i=f);this.F++;
|
||||
this.a=sjcl.hash.sha256.hash(this.a.concat(e));this.A=new sjcl.cipher.aes(this.a);for(d=0;4>d&&!(this.e[d]=this.e[d]+1|0,this.e[d]);d++);}for(d=0;d<a;d+=4)0===(d+1)%this.Q&&A(this),e=B(this),c.push(e[0],e[1],e[2],e[3]);A(this);return c.slice(0,a)},setDefaultParanoia:function(a){this.B=a},addEntropy:function(a,b,c){c=c||"user";var d,e,f=(new Date).valueOf(),g=this.t[c],h=this.isReady(),l=0;d=this.J[c];d===t&&(d=this.J[c]=this.T++);g===t&&(g=this.t[c]=0);this.t[c]=(this.t[c]+1)%this.b.length;switch(typeof a){case "number":b===
|
||||
t&&(b=1);this.b[g].update([d,this.C++,1,b,f,1,a|0]);break;case "object":c=Object.prototype.toString.call(a);if("[object Uint32Array]"===c){e=[];for(c=0;c<a.length;c++)e.push(a[c]);a=e}else{"[object Array]"!==c&&(l=1);for(c=0;c<a.length&&!l;c++)"number"!=typeof a[c]&&(l=1)}if(!l){if(b===t)for(c=b=0;c<a.length;c++)for(e=a[c];0<e;)b++,e>>>=1;this.b[g].update([d,this.C++,2,b,f,a.length].concat(a))}break;case "string":b===t&&(b=a.length);this.b[g].update([d,this.C++,3,b,f,a.length]);this.b[g].update(a);
|
||||
break;default:l=1}l&&q(new sjcl.exception.bug("random: addEntropy only supports number, array of numbers or string"));this.h[g]+=b;this.c+=b;h===this.l&&(this.isReady()!==this.l&&C("seeded",Math.max(this.i,this.c)),C("progress",this.getProgress()))},isReady:function(a){a=this.H[a!==t?a:this.B];return this.i&&this.i>=a?this.h[0]>this.P&&(new Date).valueOf()>this.N?this.w|this.u:this.u:this.c>=a?this.w|this.l:this.l},getProgress:function(a){a=this.H[a?a:this.B];return this.i>=a?1:this.c>a?1:this.c/
|
||||
a},startCollectors:function(){this.p||(window.addEventListener?(window.addEventListener("load",this.r,u),window.addEventListener("mousemove",this.s,u)):document.attachEvent?(document.attachEvent("onload",this.r),document.attachEvent("onmousemove",this.s)):q(new sjcl.exception.bug("can't attach event")),this.p=!0)},stopCollectors:function(){this.p&&(window.removeEventListener?(window.removeEventListener("load",this.r,u),window.removeEventListener("mousemove",this.s,u)):window.detachEvent&&(window.detachEvent("onload",
|
||||
this.r),window.detachEvent("onmousemove",this.s)),this.p=u)},addEventListener:function(a,b){this.z[a][this.S++]=b},removeEventListener:function(a,b){var c,d,e=this.z[a],f=[];for(d in e)e.hasOwnProperty(d)&&e[d]===b&&f.push(d);for(c=0;c<f.length;c++)d=f[c],delete e[d]},s:function(a){sjcl.random.addEntropy([a.x||a.clientX||a.offsetX||0,a.y||a.clientY||a.offsetY||0],2,"mouse")},r:function(){sjcl.random.addEntropy((new Date).valueOf(),2,"loadtime")}};
|
||||
function C(a,b){var c,d=sjcl.random.z[a],e=[];for(c in d)d.hasOwnProperty(c)&&e.push(d[c]);for(c=0;c<e.length;c++)e[c](b)}function A(a){a.a=B(a).concat(B(a));a.A=new sjcl.cipher.aes(a.a)}function B(a){for(var b=0;4>b&&!(a.e[b]=a.e[b]+1|0,a.e[b]);b++);return a.A.encrypt(a.e)}sjcl.random=new sjcl.prng(6);try{var D=new Uint32Array(32);crypto.getRandomValues(D);sjcl.random.addEntropy(D,1024,"crypto['getRandomValues']")}catch(E){}
|
||||
sjcl.json={defaults:{v:1,iter:1E3,ks:128,ts:64,mode:"ccm",adata:"",cipher:"aes"},encrypt:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json,f=e.d({iv:sjcl.random.randomWords(4,0)},e.defaults),g;e.d(f,c);c=f.adata;"string"===typeof f.salt&&(f.salt=sjcl.codec.base64.toBits(f.salt));"string"===typeof f.iv&&(f.iv=sjcl.codec.base64.toBits(f.iv));(!sjcl.mode[f.mode]||!sjcl.cipher[f.cipher]||"string"===typeof a&&100>=f.iter||64!==f.ts&&96!==f.ts&&128!==f.ts||128!==f.ks&&192!==f.ks&&0x100!==f.ks||2>f.iv.length||
|
||||
4<f.iv.length)&&q(new sjcl.exception.invalid("json encrypt: invalid parameters"));"string"===typeof a?(g=sjcl.misc.cachedPbkdf2(a,f),a=g.key.slice(0,f.ks/32),f.salt=g.salt):sjcl.ecc&&a instanceof sjcl.ecc.elGamal.publicKey&&(g=a.kem(),f.kemtag=g.tag,a=g.key.slice(0,f.ks/32));"string"===typeof b&&(b=sjcl.codec.utf8String.toBits(b));"string"===typeof c&&(c=sjcl.codec.utf8String.toBits(c));g=new sjcl.cipher[f.cipher](a);e.d(d,f);d.key=a;f.ct=sjcl.mode[f.mode].encrypt(g,b,f.iv,c,f.ts);return e.encode(f)},
|
||||
decrypt:function(a,b,c,d){c=c||{};d=d||{};var e=sjcl.json;b=e.d(e.d(e.d({},e.defaults),e.decode(b)),c,!0);var f;c=b.adata;"string"===typeof b.salt&&(b.salt=sjcl.codec.base64.toBits(b.salt));"string"===typeof b.iv&&(b.iv=sjcl.codec.base64.toBits(b.iv));(!sjcl.mode[b.mode]||!sjcl.cipher[b.cipher]||"string"===typeof a&&100>=b.iter||64!==b.ts&&96!==b.ts&&128!==b.ts||128!==b.ks&&192!==b.ks&&0x100!==b.ks||!b.iv||2>b.iv.length||4<b.iv.length)&&q(new sjcl.exception.invalid("json decrypt: invalid parameters"));
|
||||
"string"===typeof a?(f=sjcl.misc.cachedPbkdf2(a,b),a=f.key.slice(0,b.ks/32),b.salt=f.salt):sjcl.ecc&&a instanceof sjcl.ecc.elGamal.secretKey&&(a=a.unkem(sjcl.codec.base64.toBits(b.kemtag)).slice(0,b.ks/32));"string"===typeof c&&(c=sjcl.codec.utf8String.toBits(c));f=new sjcl.cipher[b.cipher](a);c=sjcl.mode[b.mode].decrypt(f,b.ct,b.iv,c,b.ts);e.d(d,b);d.key=a;return sjcl.codec.utf8String.fromBits(c)},encode:function(a){var b,c="{",d="";for(b in a)if(a.hasOwnProperty(b))switch(b.match(/^[a-z0-9]+$/i)||
|
||||
q(new sjcl.exception.invalid("json encode: invalid property name")),c+=d+'"'+b+'":',d=",",typeof a[b]){case "number":case "boolean":c+=a[b];break;case "string":c+='"'+escape(a[b])+'"';break;case "object":c+='"'+sjcl.codec.base64.fromBits(a[b],0)+'"';break;default:q(new sjcl.exception.bug("json encode: unsupported type"))}return c+"}"},decode:function(a){a=a.replace(/\s/g,"");a.match(/^\{.*\}$/)||q(new sjcl.exception.invalid("json decode: this isn't json!"));a=a.replace(/^\{|\}$/g,"").split(/,/);var b=
|
||||
{},c,d;for(c=0;c<a.length;c++)(d=a[c].match(/^(?:(["']?)([a-z][a-z0-9]*)\1):(?:(\d+)|"([a-z0-9+\/%*_.@=\-]*)")$/i))||q(new sjcl.exception.invalid("json decode: this isn't json!")),b[d[2]]=d[3]?parseInt(d[3],10):d[2].match(/^(ct|salt|iv)$/)?sjcl.codec.base64.toBits(d[4]):unescape(d[4]);return b},d:function(a,b,c){a===t&&(a={});if(b===t)return a;for(var d in b)b.hasOwnProperty(d)&&(c&&(a[d]!==t&&a[d]!==b[d])&&q(new sjcl.exception.invalid("required parameter overridden")),a[d]=b[d]);return a},X:function(a,
|
||||
b){var c={},d;for(d in a)a.hasOwnProperty(d)&&a[d]!==b[d]&&(c[d]=a[d]);return c},W:function(a,b){var c={},d;for(d=0;d<b.length;d++)a[b[d]]!==t&&(c[b[d]]=a[b[d]]);return c}};sjcl.encrypt=sjcl.json.encrypt;sjcl.decrypt=sjcl.json.decrypt;sjcl.misc.V={};
|
||||
sjcl.misc.cachedPbkdf2=function(a,b){var c=sjcl.misc.V,d;b=b||{};d=b.iter||1E3;c=c[a]=c[a]||{};d=c[d]=c[d]||{firstSalt:b.salt&&b.salt.length?b.salt.slice(0):sjcl.random.randomWords(2,0)};c=b.salt===t?d.firstSalt:b.salt;d[c]=d[c]||sjcl.misc.pbkdf2(a,c,b.iter);return{key:d[c].slice(0),salt:c.slice(0)}};
|
245
media/js/uuid.js
Normal file
245
media/js/uuid.js
Normal file
@@ -0,0 +1,245 @@
|
||||
// uuid.js
|
||||
//
|
||||
// Copyright (c) 2010-2012 Robert Kieffer
|
||||
// MIT License - http://opensource.org/licenses/mit-license.php
|
||||
|
||||
(function() {
|
||||
var _global = this;
|
||||
|
||||
// Unique ID creation requires a high quality random # generator. We feature
|
||||
// detect to determine the best RNG source, normalizing to a function that
|
||||
// returns 128-bits of randomness, since that's what's usually required
|
||||
var _rng;
|
||||
|
||||
// Node.js crypto-based RNG - http://nodejs.org/docs/v0.6.2/api/crypto.html
|
||||
//
|
||||
// Moderately fast, high quality
|
||||
if (typeof(require) == 'function') {
|
||||
try {
|
||||
var _rb = require('crypto').randomBytes;
|
||||
_rng = _rb && function() {return _rb(16);};
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
if (!_rng && _global.crypto && crypto.getRandomValues) {
|
||||
// WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto
|
||||
//
|
||||
// Moderately fast, high quality
|
||||
var _rnds8 = new Uint8Array(16);
|
||||
_rng = function whatwgRNG() {
|
||||
crypto.getRandomValues(_rnds8);
|
||||
return _rnds8;
|
||||
};
|
||||
}
|
||||
|
||||
if (!_rng) {
|
||||
// Math.random()-based (RNG)
|
||||
//
|
||||
// If all else fails, use Math.random(). It's fast, but is of unspecified
|
||||
// quality.
|
||||
var _rnds = new Array(16);
|
||||
_rng = function() {
|
||||
for (var i = 0, r; i < 16; i++) {
|
||||
if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
|
||||
_rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
|
||||
}
|
||||
|
||||
return _rnds;
|
||||
};
|
||||
}
|
||||
|
||||
// Buffer class to use
|
||||
var BufferClass = typeof(Buffer) == 'function' ? Buffer : Array;
|
||||
|
||||
// Maps for number <-> hex string conversion
|
||||
var _byteToHex = [];
|
||||
var _hexToByte = {};
|
||||
for (var i = 0; i < 256; i++) {
|
||||
_byteToHex[i] = (i + 0x100).toString(16).substr(1);
|
||||
_hexToByte[_byteToHex[i]] = i;
|
||||
}
|
||||
|
||||
// **`parse()` - Parse a UUID into it's component bytes**
|
||||
function parse(s, buf, offset) {
|
||||
var i = (buf && offset) || 0, ii = 0;
|
||||
|
||||
buf = buf || [];
|
||||
s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) {
|
||||
if (ii < 16) { // Don't overflow!
|
||||
buf[i + ii++] = _hexToByte[oct];
|
||||
}
|
||||
});
|
||||
|
||||
// Zero out remaining bytes if string was short
|
||||
while (ii < 16) {
|
||||
buf[i + ii++] = 0;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
// **`unparse()` - Convert UUID byte array (ala parse()) into a string**
|
||||
function unparse(buf, offset) {
|
||||
var i = offset || 0, bth = _byteToHex;
|
||||
return bth[buf[i++]] + bth[buf[i++]] +
|
||||
bth[buf[i++]] + bth[buf[i++]] + '-' +
|
||||
bth[buf[i++]] + bth[buf[i++]] + '-' +
|
||||
bth[buf[i++]] + bth[buf[i++]] + '-' +
|
||||
bth[buf[i++]] + bth[buf[i++]] + '-' +
|
||||
bth[buf[i++]] + bth[buf[i++]] +
|
||||
bth[buf[i++]] + bth[buf[i++]] +
|
||||
bth[buf[i++]] + bth[buf[i++]];
|
||||
}
|
||||
|
||||
// **`v1()` - Generate time-based UUID**
|
||||
//
|
||||
// Inspired by https://github.com/LiosK/UUID.js
|
||||
// and http://docs.python.org/library/uuid.html
|
||||
|
||||
// random #'s we need to init node and clockseq
|
||||
var _seedBytes = _rng();
|
||||
|
||||
// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
|
||||
var _nodeId = [
|
||||
_seedBytes[0] | 0x01,
|
||||
_seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5]
|
||||
];
|
||||
|
||||
// Per 4.2.2, randomize (14 bit) clockseq
|
||||
var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff;
|
||||
|
||||
// Previous uuid creation time
|
||||
var _lastMSecs = 0, _lastNSecs = 0;
|
||||
|
||||
// See https://github.com/broofa/node-uuid for API details
|
||||
function v1(options, buf, offset) {
|
||||
var i = buf && offset || 0;
|
||||
var b = buf || [];
|
||||
|
||||
options = options || {};
|
||||
|
||||
var clockseq = options.clockseq != null ? options.clockseq : _clockseq;
|
||||
|
||||
// UUID timestamps are 100 nano-second units since the Gregorian epoch,
|
||||
// (1582-10-15 00:00). JSNumbers aren't precise enough for this, so
|
||||
// time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
|
||||
// (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
|
||||
var msecs = options.msecs != null ? options.msecs : new Date().getTime();
|
||||
|
||||
// Per 4.2.1.2, use count of uuid's generated during the current clock
|
||||
// cycle to simulate higher resolution clock
|
||||
var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1;
|
||||
|
||||
// Time since last uuid creation (in msecs)
|
||||
var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
|
||||
|
||||
// Per 4.2.1.2, Bump clockseq on clock regression
|
||||
if (dt < 0 && options.clockseq == null) {
|
||||
clockseq = clockseq + 1 & 0x3fff;
|
||||
}
|
||||
|
||||
// Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
|
||||
// time interval
|
||||
if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) {
|
||||
nsecs = 0;
|
||||
}
|
||||
|
||||
// Per 4.2.1.2 Throw error if too many uuids are requested
|
||||
if (nsecs >= 10000) {
|
||||
throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
|
||||
}
|
||||
|
||||
_lastMSecs = msecs;
|
||||
_lastNSecs = nsecs;
|
||||
_clockseq = clockseq;
|
||||
|
||||
// Per 4.1.4 - Convert from unix epoch to Gregorian epoch
|
||||
msecs += 12219292800000;
|
||||
|
||||
// `time_low`
|
||||
var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
|
||||
b[i++] = tl >>> 24 & 0xff;
|
||||
b[i++] = tl >>> 16 & 0xff;
|
||||
b[i++] = tl >>> 8 & 0xff;
|
||||
b[i++] = tl & 0xff;
|
||||
|
||||
// `time_mid`
|
||||
var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
|
||||
b[i++] = tmh >>> 8 & 0xff;
|
||||
b[i++] = tmh & 0xff;
|
||||
|
||||
// `time_high_and_version`
|
||||
b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
|
||||
b[i++] = tmh >>> 16 & 0xff;
|
||||
|
||||
// `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
|
||||
b[i++] = clockseq >>> 8 | 0x80;
|
||||
|
||||
// `clock_seq_low`
|
||||
b[i++] = clockseq & 0xff;
|
||||
|
||||
// `node`
|
||||
var node = options.node || _nodeId;
|
||||
for (var n = 0; n < 6; n++) {
|
||||
b[i + n] = node[n];
|
||||
}
|
||||
|
||||
return buf ? buf : unparse(b);
|
||||
}
|
||||
|
||||
// **`v4()` - Generate random UUID**
|
||||
|
||||
// See https://github.com/broofa/node-uuid for API details
|
||||
function v4(options, buf, offset) {
|
||||
// Deprecated - 'format' argument, as supported in v1.2
|
||||
var i = buf && offset || 0;
|
||||
|
||||
if (typeof(options) == 'string') {
|
||||
buf = options == 'binary' ? new BufferClass(16) : null;
|
||||
options = null;
|
||||
}
|
||||
options = options || {};
|
||||
|
||||
var rnds = options.random || (options.rng || _rng)();
|
||||
|
||||
// Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
|
||||
rnds[6] = (rnds[6] & 0x0f) | 0x40;
|
||||
rnds[8] = (rnds[8] & 0x3f) | 0x80;
|
||||
|
||||
// Copy bytes to buffer, if provided
|
||||
if (buf) {
|
||||
for (var ii = 0; ii < 16; ii++) {
|
||||
buf[i + ii] = rnds[ii];
|
||||
}
|
||||
}
|
||||
|
||||
return buf || unparse(rnds);
|
||||
}
|
||||
|
||||
// Export public API
|
||||
var uuid = v4;
|
||||
uuid.v1 = v1;
|
||||
uuid.v4 = v4;
|
||||
uuid.parse = parse;
|
||||
uuid.unparse = unparse;
|
||||
uuid.BufferClass = BufferClass;
|
||||
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Publish as AMD module
|
||||
define(function() {return uuid;});
|
||||
} else if (typeof(module) != 'undefined' && module.exports) {
|
||||
// Publish as node.js module
|
||||
module.exports = uuid;
|
||||
} else {
|
||||
// Publish as global (in browsers)
|
||||
var _previousRoot = _global.uuid;
|
||||
|
||||
// **`noConflict()` - (browser only) to reset global 'uuid' var**
|
||||
uuid.noConflict = function() {
|
||||
_global.uuid = _previousRoot;
|
||||
return uuid;
|
||||
};
|
||||
|
||||
_global.uuid = uuid;
|
||||
}
|
||||
}).call(this);
|
@@ -7,7 +7,7 @@ These are referenced from the setting TEMPLATE_CONTEXT_PROCESSORS and used by
|
||||
RequestContext.
|
||||
"""
|
||||
from seahub.settings import SEAFILE_VERSION, SITE_TITLE, SITE_NAME, SITE_BASE, \
|
||||
ENABLE_SIGNUP, MAX_FILE_NAME, BRANDING_CSS, LOGO_PATH, LOGO_URL
|
||||
ENABLE_SIGNUP, MAX_FILE_NAME, BRANDING_CSS, LOGO_PATH, LOGO_URL, KEEP_ENC_REPO_PASSWD
|
||||
try:
|
||||
from seahub.settings import BUSINESS_MODE
|
||||
except ImportError:
|
||||
@@ -54,5 +54,6 @@ def base(request):
|
||||
'max_file_name': MAX_FILE_NAME,
|
||||
'has_file_search': HAS_FILE_SEARCH,
|
||||
'enable_pubfile': ENABLE_PUBFILE,
|
||||
'keep_enc_repo_passwd': KEEP_ENC_REPO_PASSWD,
|
||||
}
|
||||
|
||||
|
@@ -3,7 +3,9 @@ from django.shortcuts import render_to_response
|
||||
from django.template import RequestContext
|
||||
from seaserv import get_repo, is_passwd_set
|
||||
|
||||
from seahub.utils import check_and_get_org_by_repo, check_and_get_org_by_group
|
||||
from seahub.utils import check_and_get_org_by_repo, check_and_get_org_by_group, render_error
|
||||
from django.utils.translation import ugettext as _
|
||||
from seahub.settings import KEEP_ENC_REPO_PASSWD
|
||||
|
||||
def sys_staff_required(func):
|
||||
"""
|
||||
@@ -62,12 +64,18 @@ def repo_passwd_set_required(func):
|
||||
if not repo:
|
||||
raise Http404
|
||||
username = request.user.username
|
||||
if repo.encrypted and not is_passwd_set(repo_id, username):
|
||||
if repo.encrypted:
|
||||
if (repo.enc_version == 1 or (repo.enc_version == 2 and KEEP_ENC_REPO_PASSWD)) \
|
||||
and not is_passwd_set(repo_id, username):
|
||||
# Redirect uesr to decrypt repo page.
|
||||
return render_to_response('decrypt_repo_form.html', {
|
||||
'repo': repo,
|
||||
'next': request.get_full_path(),
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
if repo.enc_version == 2 and not KEEP_ENC_REPO_PASSWD:
|
||||
return render_error(request, _(u'Files in this library can not be viewed online.'))
|
||||
|
||||
return func(request, *args, **kwargs)
|
||||
return _decorated
|
||||
|
||||
|
@@ -64,7 +64,9 @@ class RepoCreateForm(forms.Form):
|
||||
'min_length': _(u'Password is too short (minimum is 3 characters)'),
|
||||
'max_length': _(u'Password is too long (maximum is 30 characters)'),
|
||||
})
|
||||
|
||||
uuid = forms.CharField(required=False)
|
||||
magic_str = forms.CharField(required=False)
|
||||
random_key = forms.CharField(required=False)
|
||||
def clean_repo_name(self):
|
||||
repo_name = self.cleaned_data['repo_name']
|
||||
if not is_valid_filename(repo_name):
|
||||
@@ -74,23 +76,24 @@ class RepoCreateForm(forms.Form):
|
||||
return repo_name
|
||||
|
||||
def clean(self):
|
||||
"""
|
||||
Verifiy that the values entered into the two password fields
|
||||
match.
|
||||
"""
|
||||
if 'passwd' in self.cleaned_data and 'passwd_again' in self.cleaned_data:
|
||||
encryption = self.cleaned_data['encryption']
|
||||
if int(encryption) == 0:
|
||||
# This prevents the case that form has passwords but the
|
||||
# encryption checkbox is not selected.
|
||||
self.cleaned_data['passwd'] = None
|
||||
self.cleaned_data['passwd_again'] = None
|
||||
return self.cleaned_data
|
||||
else:
|
||||
|
||||
if settings.KEEP_ENC_REPO_PASSWD:
|
||||
passwd = self.cleaned_data['passwd']
|
||||
passwd_again = self.cleaned_data['passwd_again']
|
||||
if not (passwd and passwd_again):
|
||||
raise forms.ValidationError(_("Password is required"))
|
||||
if passwd != passwd_again:
|
||||
raise forms.ValidationError(_("Passwords don't match"))
|
||||
else:
|
||||
uuid = self.cleaned_data['uuid']
|
||||
magic_str = self.cleaned_data['magic_str']
|
||||
random_key = self.cleaned_data['random_key']
|
||||
if not (uuid and magic_str and random_key):
|
||||
raise forms.ValidationError(_("Argument missing"))
|
||||
|
||||
return self.cleaned_data
|
||||
|
||||
class SharedRepoCreateForm(RepoCreateForm):
|
||||
|
@@ -169,6 +169,12 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_script %}
|
||||
{% if not keep_enc_repo_passwd %}
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/uuid.js"></script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/sjcl.min.js"></script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/codecBytes.js"></script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/CryptoJS/rollups/aes.js"></script>
|
||||
{% endif %}
|
||||
<script type="text/javascript">
|
||||
addConfirmTo($('#quit-group'), {
|
||||
'title':'{% trans "Quit Group" %}',
|
||||
|
@@ -29,6 +29,7 @@ from seaserv import ccnet_threaded_rpc, seafserv_threaded_rpc, seafserv_rpc, \
|
||||
get_personal_groups, create_org_repo, get_org_group_repos, \
|
||||
check_permission, is_passwd_set, remove_repo, \
|
||||
unshare_group_repo, get_file_id_by_path, post_empty_file, del_file
|
||||
from seaserv import seafile_api
|
||||
from pysearpc import SearpcError
|
||||
|
||||
from decorators import group_staff_required
|
||||
@@ -46,7 +47,7 @@ from seahub.wiki import get_group_wiki_repo, get_group_wiki_page, convert_wiki_l
|
||||
get_wiki_pages
|
||||
from seahub.wiki.models import WikiDoesNotExist, WikiPageMissing, GroupWiki
|
||||
from seahub.wiki.utils import clean_page_name, get_wiki_dirent
|
||||
from seahub.settings import SITE_ROOT, SITE_NAME, MEDIA_URL
|
||||
from seahub.settings import SITE_ROOT, SITE_NAME, MEDIA_URL, KEEP_ENC_REPO_PASSWD
|
||||
from seahub.shortcuts import get_first_object_or_none
|
||||
from seahub.utils import render_error, render_permission_error, string2list, \
|
||||
check_and_get_org_by_group, gen_file_get_url, get_file_type_and_ext, \
|
||||
@@ -914,7 +915,7 @@ def create_group_repo(request, group_id):
|
||||
content_type = 'application/json; charset=utf-8'
|
||||
|
||||
def json_error(err_msg):
|
||||
result = {'error': [err_msg]}
|
||||
result = {'error': err_msg}
|
||||
return HttpResponseBadRequest(json.dumps(result),
|
||||
content_type=content_type)
|
||||
group_id = int(group_id)
|
||||
@@ -928,13 +929,17 @@ def create_group_repo(request, group_id):
|
||||
|
||||
form = SharedRepoCreateForm(request.POST)
|
||||
if not form.is_valid():
|
||||
return json_error(form.errors)
|
||||
return json_error(str(form.errors.values()[0]))
|
||||
else:
|
||||
repo_name = form.cleaned_data['repo_name']
|
||||
repo_desc = form.cleaned_data['repo_desc']
|
||||
permission = form.cleaned_data['permission']
|
||||
encrypted = form.cleaned_data['encryption']
|
||||
encryption = int(form.cleaned_data['encryption'])
|
||||
|
||||
passwd = form.cleaned_data['passwd']
|
||||
uuid = form.cleaned_data['uuid']
|
||||
magic_str = form.cleaned_data['magic_str']
|
||||
random_key = form.cleaned_data['random_key']
|
||||
user = request.user.username
|
||||
|
||||
org, base_template = check_and_get_org_by_group(group.id, user)
|
||||
@@ -967,7 +972,18 @@ def create_group_repo(request, group_id):
|
||||
content_type=content_type)
|
||||
else:
|
||||
# create group repo in user context
|
||||
repo_id = create_repo(repo_name, repo_desc, user, passwd)
|
||||
try:
|
||||
if not encryption:
|
||||
repo_id = seafile_api.create_repo(repo_name, repo_desc, user, None)
|
||||
else:
|
||||
if KEEP_ENC_REPO_PASSWD:
|
||||
repo_id = seafile_api.create_repo(repo_name, repo_desc, user, passwd)
|
||||
else:
|
||||
repo_id = seafile_api.create_enc_repo(uuid, repo_name, repo_desc, user, magic_str, random_key, enc_version=2)
|
||||
|
||||
except SearpcError, e:
|
||||
repo_id = None
|
||||
|
||||
if not repo_id:
|
||||
return json_error(_(u'Failed to create'))
|
||||
|
||||
|
@@ -180,6 +180,9 @@ AUTHENTICATION_BACKENDS = (
|
||||
|
||||
ACCOUNT_ACTIVATION_DAYS = 7
|
||||
|
||||
# keep password of encrypted repo (on the server)
|
||||
KEEP_ENC_REPO_PASSWD = True
|
||||
|
||||
# File preview
|
||||
FILE_PREVIEW_MAX_SIZE = 30 * 1024 * 1024
|
||||
OFFICE_PREVIEW_MAX_SIZE = 2 * 1024 * 1024
|
||||
|
@@ -58,7 +58,7 @@
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if request.user.is_authenticated %}
|
||||
<a href="{{ SITE_ROOT }}accounts/logout/" class="icon-signout top-link" title="{% trans "Log out" %}"></a>
|
||||
<a href="{{ SITE_ROOT }}accounts/logout/" class="icon-signout top-link" title="{% trans "Log out" %}" id="logout"></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
@@ -6,17 +6,31 @@
|
||||
<div class="repo-file-list-inner-container">
|
||||
<div class="repo-file-list-not-show">
|
||||
<p class="access-notice">{% trans "This library is encrypted. Please input the password if you want to browse it online. And the password will be kept on the server for only 1 hour." %}</p>
|
||||
<form action="{{ SITE_ROOT }}repo/{{ repo.id }}/?next={{ next }}" method="post">{% csrf_token %}
|
||||
<form action="{{ SITE_ROOT }}repo/{{ repo.id }}/?next={{ next }}" method="post" id="repo-decrypt-form">{% csrf_token %}
|
||||
<label>{% trans "Password: " %}</label>
|
||||
<input type="hidden" name="repo_id" value="{{ repo.id }}" />
|
||||
<input type="hidden" name="username" value="{{ request.user.username }}" />
|
||||
<input id="id_password" type="password" name="password" maxlength="64" autofocus />
|
||||
<input type="password" name="password" maxlength="64" autofocus />
|
||||
<input type="submit" value="{% trans "Submit" %}" />
|
||||
<p class="error hide"></p>
|
||||
{% for error in form.errors.values %}
|
||||
<p class="error">{{ error|escape }}</p>
|
||||
{{ error|escape }}
|
||||
{% endfor %}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block extra_script %}
|
||||
<script type="text/javascript">
|
||||
$('#repo-decrypt-form').submit(function() {
|
||||
var form = $(this),
|
||||
pwd = $('[name="password"]', form).val(),
|
||||
err = $('.error',form);
|
||||
if (!$.trim(pwd)) {
|
||||
err.html("{% trans "Please enter the password." %}").removeClass('hide');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@@ -115,6 +115,12 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_script %}
|
||||
{% if not keep_enc_repo_passwd %}
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/uuid.js"></script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/sjcl.min.js"></script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/codecBytes.js"></script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/CryptoJS/rollups/aes.js"></script>
|
||||
{% endif %}
|
||||
<script type="text/javascript">
|
||||
{% if quota > 0 %}
|
||||
{% if CALC_SHARE_USAGE %}
|
||||
|
@@ -56,6 +56,12 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_script %}
|
||||
{% if not keep_enc_repo_passwd %}
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/uuid.js"></script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/sjcl.min.js"></script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/codecBytes.js"></script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/CryptoJS/rollups/aes.js"></script>
|
||||
{% endif %}
|
||||
<script type="text/javascript">
|
||||
$(".download-btn").click(function() {
|
||||
window.open('{{ SITE_ROOT }}seafile_access_check/?repo_id=' + $(this).attr('data'));
|
||||
|
@@ -7,6 +7,9 @@
|
||||
<style type="text/css">
|
||||
#main { width:auto; }
|
||||
#footer { display:none; }
|
||||
{% if repo.enc_version == 2 and not keep_enc_repo_passwd and repo.encrypted %}
|
||||
#main { display:none; }
|
||||
{% endif %}
|
||||
</style>
|
||||
<!-- Shim to make HTML5 elements usable in older Internet Explorer versions -->
|
||||
<!--[if lt IE 9]><script src="{{ MEDIA_URL}}js/html5shiv.js"></script><![endif]-->
|
||||
@@ -57,7 +60,12 @@
|
||||
<p class="error">{% trans "The owner of this library has ran out of space." %}</p>
|
||||
{% else %}
|
||||
<form id="upload-file-form" enctype="multipart/form-data" method="post" action="{{ajax_upload_url}}">{% csrf_token %}
|
||||
<input type="hidden" name="parent_dir" id="parent_dir" value="{{ path }}" />
|
||||
{% if repo.enc_version == 2 and not keep_enc_repo_passwd and repo.encrypted %}
|
||||
<input type="file" name="file" /><br />
|
||||
<p class="error hide">{% trans "Please select a file at first." %}</p>
|
||||
<input type="button" value="{% trans "Submit" %}" />
|
||||
{% else %}
|
||||
<input type="hidden" name="parent_dir" value="{{ path }}" />
|
||||
<div class="row fileupload-buttonbar">
|
||||
<div>
|
||||
<span class="fileinput-button vam">
|
||||
@@ -86,6 +94,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-striped"><tbody class="files" data-toggle="modal-gallery" data-target="#modal-gallery"></tbody></table>
|
||||
{% endif %}
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -97,6 +106,13 @@
|
||||
{% else %}
|
||||
<form id="update-file-form" enctype="multipart/form-data" method="post" action="">{% csrf_token %}
|
||||
<input type="hidden" name="target_file" />
|
||||
|
||||
{% if repo.enc_version == 2 and not keep_enc_repo_passwd and repo.encrypted %}
|
||||
<input type="file" name="file" /><br />
|
||||
<p class="error hide">{% trans "Please select a file at first." %}</p>
|
||||
<input type="button" value="{% trans "Submit" %}" />
|
||||
{% else %}
|
||||
|
||||
<div class="fileupload-buttonbar">
|
||||
<span class="fileinput-button vam">
|
||||
<span>{% trans "Choose a file" %}</span>
|
||||
@@ -111,6 +127,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-striped"><tbody class="files" data-toggle="modal-gallery" data-target="#modal-gallery"></tbody></table>
|
||||
{% endif %}
|
||||
</form>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -183,6 +200,73 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_script %}
|
||||
{% if repo.enc_version == 2 and not keep_enc_repo_passwd and repo.encrypted %}
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/sjcl.min.js"></script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/codecBytes.js"></script>
|
||||
<script type="text/javascript" src="{{MEDIA_URL}}js/CryptoJS/rollups/aes.js"></script>
|
||||
<script type="text/javascript">
|
||||
var valid_time_period = 60 * 60 * 1000; // passwd will be kept for 1 h
|
||||
var enc_key, enc_iv;
|
||||
if ('localStorage' in window && window['localStorage'] !== null) {
|
||||
// 'localStorage' is supported
|
||||
var last_decrypt_t = localStorage['{{repo.id}}_decrypt_t'];
|
||||
// decrypt at the first time, or when last decryption is more than 1 hour ago
|
||||
if (!last_decrypt_t || (new Date().getTime() - last_decrypt_t > valid_time_period)) {
|
||||
decrypt_repo();
|
||||
} else {
|
||||
$('#main').show();
|
||||
enc_key = localStorage['{{repo.id}}_enc_key'];
|
||||
enc_iv = localStorage['{{repo.id}}_enc_iv'];
|
||||
}
|
||||
} else {
|
||||
// 'localStorage' is not supported, decrypt every time
|
||||
decrypt_repo();
|
||||
}
|
||||
function decrypt_repo() {
|
||||
var decrypt_form = $('<form id="repo-decrypt" style="width:928px;padding:10px 10px 15px;border:1px solid #ddd;border-radius:3px;margin:2em auto 0"> <p>{% trans "This library is encrypted. Please input the password if you want to browse it online. And the password will be kept in the browser for only 1 hour." %}</p> <input type="password" name="password" maxlength="64" autofocus /> <input type="submit" value="{% trans "Submit" %}" /> <p class="error hide"></p> </form>');
|
||||
$('#header').after(decrypt_form);
|
||||
$('[type="submit"]', decrypt_form).click(function() {
|
||||
var passwd = $('[name="password"]', decrypt_form).val(),
|
||||
err = $('.error', decrypt_form);
|
||||
if (!$.trim(passwd)) {
|
||||
err.html("{% trans "Please enter the password." %}").removeClass('hide');
|
||||
return false;
|
||||
}
|
||||
|
||||
var salt = sjcl.codec.bytes.toBits([0xda, 0x90, 0x45, 0xc3, 0x06, 0xc7, 0xcc, 0x26]);
|
||||
var magic_array = sjcl.misc.pbkdf2('{{repo.id}}' + passwd, salt, 1000, 32*8, null),
|
||||
magic_str = sjcl.codec.hex.fromBits(magic_array); //convert to hex
|
||||
if (magic_str == '{{repo.magic}}') {
|
||||
decrypt_form.remove();
|
||||
$('#main').show();
|
||||
|
||||
var key_array = sjcl.misc.pbkdf2(passwd, salt, 1000, 32*8, null);
|
||||
var iv_array = sjcl.misc.pbkdf2(key_array, salt, 10, 32*8, null);
|
||||
var key = sjcl.codec.hex.fromBits(key_array);
|
||||
var iv = sjcl.codec.hex.fromBits(iv_array);
|
||||
|
||||
var secret_key_array = CryptoJS.AES.decrypt(CryptoJS.enc.Hex.parse('{{repo.random_key}}').toString(CryptoJS.enc.Base64), CryptoJS.enc.Hex.parse(key), {iv: CryptoJS.enc.Hex.parse(iv)});
|
||||
var secret_key = secret_key_array.toString(CryptoJS.enc.Hex);
|
||||
|
||||
var enc_key_array = sjcl.misc.pbkdf2(sjcl.codec.hex.toBits(secret_key), salt, 1000, 32*8, null);
|
||||
var enc_iv_array = sjcl.misc.pbkdf2(enc_key_array, salt, 10, 32*8, null);
|
||||
|
||||
enc_key = sjcl.codec.hex.fromBits(enc_key_array);
|
||||
enc_iv = sjcl.codec.hex.fromBits(enc_iv_array);
|
||||
if ('localStorage' in window && window['localStorage'] !== null) {
|
||||
var repo_id = '{{repo.id}}';
|
||||
localStorage[repo_id + '_decrypt_t'] = new Date().getTime();
|
||||
localStorage[repo_id + '_enc_key'] = enc_key;
|
||||
localStorage[repo_id + '_enc_iv'] = enc_iv;
|
||||
}
|
||||
} else {
|
||||
err.html("{% trans "Wrong password" %}").removeClass('hide');
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{% endif %}
|
||||
{% upload_js %}
|
||||
<script src="{{ MEDIA_URL}}js/jquery.ui.widget.js"></script>
|
||||
<script src="{{ MEDIA_URL}}js/tmpl.min.js"></script>
|
||||
@@ -428,6 +512,95 @@ $('#mv-dirents, #cp-dirents').click(function() {
|
||||
});
|
||||
});
|
||||
|
||||
{% if repo.enc_version == 2 and not keep_enc_repo_passwd and repo.encrypted %}
|
||||
function wordArray2ab(wordArray) {
|
||||
// Shortcuts
|
||||
var words = wordArray.words;
|
||||
var sigBytes = wordArray.sigBytes;
|
||||
|
||||
// Convert
|
||||
var u8 = new Uint8Array(sigBytes);
|
||||
for (var i = 0; i < sigBytes; i++) {
|
||||
var byte = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
||||
u8[i] = byte;
|
||||
}
|
||||
|
||||
return u8;
|
||||
}
|
||||
|
||||
function encAndSubmitFile(file, prepare_fd, submit_url) {
|
||||
function sliceFile(file) {
|
||||
file.slice = file.mozSlice || file.webkitSlice || file.slice; // compatibility
|
||||
var pos = 0;
|
||||
var slices = [];
|
||||
if (file.size == 0) {
|
||||
return [file]; // It is required to be encrypted.
|
||||
}
|
||||
while(pos < file.size){
|
||||
slices.push(file.slice(pos, pos += 1024 * 1024));
|
||||
}
|
||||
return slices;
|
||||
}
|
||||
var blocks = sliceFile(file), encrypted_blocks = [];
|
||||
var workers = [], workersCount = 4, i, len;
|
||||
for (i = 0; i < workersCount; i++) {
|
||||
workers.push(new Worker('{{MEDIA_URL}}js/file_crypto.js'));
|
||||
}
|
||||
for (i = 0, len = workers.length; i < len ; i++) {
|
||||
workers[i].addEventListener('message', onWorkerMessage, false);
|
||||
}
|
||||
for (i = 0, len = blocks.length; i < len; i++) {
|
||||
workers[i % workers.length].postMessage({
|
||||
encrypt: true,
|
||||
key: enc_key,
|
||||
iv: enc_iv,
|
||||
index: i,
|
||||
block: blocks[i]
|
||||
});
|
||||
}
|
||||
|
||||
function onWorkerMessage(e) {
|
||||
if (typeof e.data != 'object') {
|
||||
// error
|
||||
return;
|
||||
}
|
||||
encrypted_blocks.push({index: e.data.index, block: e.data.block, block_id: e.data.block_id});
|
||||
if (encrypted_blocks.length == blocks.length ) {
|
||||
onFinish();
|
||||
}
|
||||
}
|
||||
|
||||
function onFinish() {
|
||||
var ordered_enc_blocks = [], blk;
|
||||
for (var i = 0, len = encrypted_blocks.length; i < len; i++) {
|
||||
ordered_enc_blocks[encrypted_blocks[i].index] = {'id': encrypted_blocks[i].block_id, 'block': encrypted_blocks[i].block};
|
||||
}
|
||||
var fd = prepare_fd();
|
||||
for (var i = 0, len = ordered_enc_blocks.length; i < len; i++) {
|
||||
blk = new Blob([wordArray2ab(ordered_enc_blocks[i].block)], {type:''});
|
||||
fd.append('file', blk, ordered_enc_blocks[i].id);
|
||||
}
|
||||
$.ajax({
|
||||
url: submit_url,
|
||||
type: "POST",
|
||||
dataType: 'json',
|
||||
data: fd,
|
||||
processData: false, // tell jQuery not to process the data
|
||||
contentType: false, // tell jQuery not to set contentType
|
||||
beforeSend: prepareCSRFToken,
|
||||
success: function(data) {
|
||||
$.modal.close();
|
||||
reqDirData('{% url 'repo_dir_data' repo.id %}?p=' + e(cur_path));
|
||||
updateCmt();
|
||||
},
|
||||
error: function () {
|
||||
$.modal.close();
|
||||
feedback('{% trans "Failed." %}', 'error');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
{% endif %}
|
||||
// js on repo file list
|
||||
var no_file_op_popup = true;
|
||||
|
||||
@@ -435,6 +608,35 @@ function dirOP() {
|
||||
|
||||
$('.path .dir-link').click(dirlinkClick);
|
||||
|
||||
{% if repo.enc_version == 2 and not keep_enc_repo_passwd and repo.encrypted %}
|
||||
$('#upload-file').click(function () {
|
||||
$('#upload-file-dialog').modal();
|
||||
$('#simplemodal-container').css({'height':'auto'});
|
||||
|
||||
$('#upload-file-form [type="button"]').click(function() {
|
||||
var form = $('#upload-file-form');
|
||||
var file_input = $('[type="file"]', form);
|
||||
if (file_input[0].files.length == 0) {
|
||||
$('.error', form).removeClass('hide');
|
||||
return false;
|
||||
}
|
||||
var file = file_input[0].files[0];
|
||||
|
||||
var prepare_fd = function() {
|
||||
// the selected file will not be submitted
|
||||
file_input.remove();
|
||||
// get the fields in the form (e.g. csrf...token)
|
||||
var fd = new FormData(form[0]);
|
||||
fd.append('parent_dir', cur_path);
|
||||
fd.append('file_name', file.name);
|
||||
fd.append('file_size', file.size);
|
||||
return fd;
|
||||
};
|
||||
var sb_url = form.attr('action');
|
||||
encAndSubmitFile(file, prepare_fd, sb_url);
|
||||
});
|
||||
});
|
||||
{% else %}
|
||||
$('#upload-file').click(function () {
|
||||
var upload_success = false;
|
||||
$('#upload-file-dialog').modal({
|
||||
@@ -450,8 +652,10 @@ $('#upload-file').click(function () {
|
||||
});
|
||||
$('.simplemodal-wrap').css({'overflow':'auto'}); // for ie
|
||||
|
||||
var form = $('#upload-file-form');
|
||||
$('input[name="parent_dir"]', form).val(cur_path);
|
||||
var form = $('#upload-file-form'),
|
||||
parent_dir = $('input[name="parent_dir"]', form);
|
||||
|
||||
parent_dir.val(cur_path);
|
||||
|
||||
// Initialize the jQuery File Upload widget:
|
||||
form.fileupload({
|
||||
@@ -471,6 +675,7 @@ $('#upload-file').click(function () {
|
||||
window.location.href.replace(/\/repo\/[-a-z0-9]{36}\/.*/, '/media/cors/result.html?%s')
|
||||
);
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
$('#add-new-dir').click(function () {
|
||||
$('#add-new-dir-form').modal({appendTo:'#main'});
|
||||
@@ -678,6 +883,133 @@ $('.checkbox-orig', context).unbind().click(function() {
|
||||
|
||||
$('.dir-link', context).click(dirlinkClick);
|
||||
|
||||
{% if repo.enc_version == 2 and not keep_enc_repo_passwd and repo.encrypted %}
|
||||
|
||||
$('.file-download').click(function() {
|
||||
var file_name = $(this).parents('tr').attr('data-name'),
|
||||
file_id = $(this).attr('data-fileid'); // data() will convert values, for example, '000000000...' is converted to 0
|
||||
|
||||
// if file size is 0, directly download it
|
||||
if (file_id == '0000000000000000000000000000000000000000') {
|
||||
var fileAsBlob = new Blob([], {type:''});
|
||||
var URL = window.URL || window.webkitURL;
|
||||
var url = URL.createObjectURL(fileAsBlob);
|
||||
var link = $("<a>").attr("href", url).attr("download", file_name).html('Download').appendTo("body").hide();
|
||||
link[0].click();
|
||||
link.remove();
|
||||
return false;
|
||||
}
|
||||
|
||||
function showMsg(con, type) {
|
||||
if ($('.messages')[0]) {
|
||||
$('.messages').html('<li class="' + type + '">' + con + '</li>');
|
||||
} else {
|
||||
var html = '<ul class="messages"><li class="' + type + '">' + con + '</li></ul>';
|
||||
$('#main').append(html);
|
||||
}
|
||||
$('.messages').css({'left':($(window).width() - $('.messages').width())/2, 'top':10}).removeClass('hide');
|
||||
}
|
||||
|
||||
|
||||
showMsg("{% trans "Downloading..." %}", 'info');
|
||||
|
||||
$.ajax({
|
||||
url: '{{SITE_ROOT}}ajax/repo/{{repo.id}}/encrypted_file/' + file_id + '/download/',
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
var block_id_list = data['blklist'],
|
||||
block_get_url_root = data['url'];
|
||||
|
||||
var blocks = [], decrypted_blocks = [];
|
||||
|
||||
for (var i = 0, len = block_id_list.length; i < len; i++) {
|
||||
reqBlock(i);
|
||||
}
|
||||
|
||||
var str2ab = function(str) {
|
||||
var buf = new ArrayBuffer(str.length);
|
||||
var bufView = new Uint8Array(buf);
|
||||
for (var i = 0, strLen = str.length; i < strLen; i++) {
|
||||
bufView[i] = str.charCodeAt(i);
|
||||
}
|
||||
return buf;
|
||||
};
|
||||
|
||||
function reqBlock(index) {
|
||||
$.ajax({
|
||||
url: block_get_url_root + block_id_list[index],
|
||||
beforeSend:function(xhr) {
|
||||
// let JQuery not process the returned binary data: return binary str
|
||||
xhr.overrideMimeType("text/plain; charset=x-user-defined");
|
||||
},
|
||||
success: function(data, textStatus, xhr) {
|
||||
blocks.push({index: index, block: str2ab(data)});
|
||||
var msg = "{% trans "Downloading, %(num)s% complete." %}";
|
||||
showMsg(msg.replace('%(num)s', (blocks.length / block_id_list.length * 100).toFixed(0)), 'info');
|
||||
if (blocks.length == block_id_list.length) {
|
||||
// after receiving all blocks
|
||||
decrypt(blocks);
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
console.log('failed to get block ' + index);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var workers = [], workersCount = 4, i;
|
||||
for (i = 0; i < workersCount; i++) {
|
||||
workers.push(new Worker('{{MEDIA_URL}}js/file_crypto.js'));
|
||||
}
|
||||
for (i = 0; i < workers.length; i++){
|
||||
workers[i].addEventListener('message', onWorkerMessage, false);
|
||||
}
|
||||
function decrypt(blocks) {
|
||||
showMsg("{% trans "Decrypting..." %}", 'info');
|
||||
for (i = 0; i < blocks.length; i++) {
|
||||
workers[i % workers.length].postMessage({
|
||||
decrypt: true,
|
||||
key: enc_key,
|
||||
iv: enc_iv,
|
||||
index: blocks[i].index,
|
||||
block: blocks[i].block
|
||||
});
|
||||
}
|
||||
}
|
||||
function onWorkerMessage(e) {
|
||||
if (typeof e.data != 'object') {
|
||||
// error
|
||||
return;
|
||||
}
|
||||
decrypted_blocks.push({index: e.data.index, block: e.data.block});
|
||||
var msg = "{% trans "Decrypting, %(num)s% complete." %}";
|
||||
showMsg(msg.replace('%(num)s', (decrypted_blocks.length / block_id_list.length * 100).toFixed(0)), 'info');
|
||||
if (decrypted_blocks.length == block_id_list.length ) {
|
||||
onFinish();
|
||||
}
|
||||
}
|
||||
|
||||
function onFinish() {
|
||||
var ordered_decrypted_blocks = [];
|
||||
for (var i = 0, len = decrypted_blocks.length; i < len; i++) {
|
||||
ordered_decrypted_blocks[decrypted_blocks[i].index] = wordArray2ab(decrypted_blocks[i].block);
|
||||
}
|
||||
|
||||
var fileAsBlob = new Blob(ordered_decrypted_blocks, {type:''});
|
||||
var URL = window.URL || window.webkitURL;
|
||||
var url = URL.createObjectURL(fileAsBlob);
|
||||
var link = $("<a>").attr("href", url).attr("download", file_name).html('Download').appendTo("body").hide();
|
||||
link[0].click();
|
||||
showMsg("{% trans "Done!" %}", 'info');
|
||||
setTimeout(function() { $('.messages').addClass('hide'); }, 1500);
|
||||
link.remove();
|
||||
} //onFinish ends
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
var popup_tr = ''; // the tr which the shown popup belongs to
|
||||
$('#main-panel').removeClass('ovhd');
|
||||
// to fix 'height becomes 0 after sort' for some versions of chrome/ff.
|
||||
@@ -840,8 +1172,41 @@ $('.file-cp, .file-mv, .dir-cp, .dir-mv', context).click(function () {
|
||||
return false;
|
||||
});
|
||||
|
||||
{% if repo.enc_version == 2 and not keep_enc_repo_passwd and repo.encrypted %}
|
||||
$('.file-update', context).click(function() {
|
||||
var file_name = $(this).parents('.file-item').data('name');
|
||||
$('#update-file-dialog').modal();
|
||||
$('#simplemodal-container').css({'width':'auto', 'height':'auto'});
|
||||
|
||||
var file_name = $(this).parents('.file-item').attr('data-name');
|
||||
var form = $('#update-file-form');
|
||||
var hd = $('#update-file-dialog .hd');
|
||||
hd.html(hd.html().replace('%(file_name)s', '<span class="op-target">' + file_name + '</span>'));
|
||||
|
||||
$('input[name="target_file"]', form).val(cur_path + file_name);
|
||||
|
||||
$('[type="button"]', form).click(function() {
|
||||
var file_input = $('[type="file"]', form);
|
||||
if (file_input[0].files.length == 0) {
|
||||
$('.error', form).removeClass('hide');
|
||||
return false;
|
||||
}
|
||||
var file = file_input[0].files[0];
|
||||
var prepare_fd = function() {
|
||||
file_input.remove();
|
||||
var fd = new FormData(form[0]);
|
||||
fd.append('file_size', file.size);
|
||||
return fd;
|
||||
};
|
||||
var sb_url = '{{ ajax_update_url }}?head=' + $('#repo-latest-commit .commit-msg').data('cmtid');
|
||||
|
||||
encAndSubmitFile(file, prepare_fd, sb_url);
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
{% else %}
|
||||
$('.file-update', context).click(function() {
|
||||
var file_name = $(this).parents('.file-item').attr('data-name');
|
||||
var form = $('#update-file-form');
|
||||
var upload_success = false;
|
||||
$('#update-file-dialog').modal({
|
||||
@@ -882,6 +1247,7 @@ $('.file-update', context).click(function() {
|
||||
|
||||
return false;
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
$('.file-star', context).click(function() {
|
||||
var op = $(this),
|
||||
@@ -1010,12 +1376,14 @@ $('#add-new-file-form, #add-new-dir-form, #rename-form, #mv-form').submit(functi
|
||||
var name_link = $('.dirent-name a', op_obj);
|
||||
name_link.html(new_name).attr('href', name_link.attr('href').substr(0, name_link.attr('href').indexOf('?')) + '?p=' + e(path+new_name));
|
||||
$('.dirent-update', op_obj).html("{% trans "Just now" %}");
|
||||
var dld_link = $('.download', op_obj), dld_href = dld_link.attr('href');
|
||||
var dld_link;
|
||||
if (op_obj.attr('class') == 'dir-item') {
|
||||
dld_link = $('.dir-download', op_obj), dld_href = dld_link.attr('href');
|
||||
dld_link.attr('href', dld_href.substr(0, dld_href.indexOf('?')) + '?p=' + e(path+new_name));
|
||||
$('.dir-share', op_obj).data('link', '').data('token', '');
|
||||
} else {
|
||||
$('.file-star', op_obj).attr('title', "{% trans "unstarred" %}").attr('class', 'icon-star-empty file-star').attr('data-status', 'unstarred');
|
||||
dld_link = $('.file-download', op_obj), dld_href = dld_link.attr('href');
|
||||
dld_link.attr('href', dld_href.substr(0, dld_href.indexOf('?')) + '?file_name=' + e(new_name) + '&op=download');
|
||||
$('.file-share', op_obj).data('link', '').data('token', '');
|
||||
|
||||
@@ -1236,7 +1604,6 @@ function updateCmt() {
|
||||
disable($(this));
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
{% include "snippets/list_commit_detail.html" %}
|
||||
{% include "snippets/shared_link_js.html" %}
|
||||
{% include "snippets/bottom_bar.html" %}
|
||||
|
@@ -4,7 +4,11 @@
|
||||
{% block main_panel %}
|
||||
<div class="text-panel">
|
||||
<p id="msg-wait">{% trans 'Preparing, please wait...' %}</p>
|
||||
<p id="msg-client" class="error hide">{% trans "No running Seafile client is detected. If you're sure Seafile client is running, click the following link to continue downloading:" %} <br/><a href="{{ download_url }}">{{ download_url|slice:"40" }}...</a></p>
|
||||
<div id="msg-client" class="hide">
|
||||
<p style="margin-bottom:.9em;"><span class="error">{% trans "No running Seafile client version 1.x is detected." %}</span><br />{% trans "If you're sure Seafile client is running, click the following link to continue downloading:" %}<br/><a href="{{ download_url }}">{{ download_url|slice:"40" }}...</a></p>
|
||||
<p>{% trans "If you're using Seafile client version 2.0+, download the library from the client directly." %}</p>
|
||||
<img src="{{MEDIA_URL}}img/client-v2-download-lib.png" alt="" />
|
||||
</div>
|
||||
<p id="msg-version" class="error hide">{% trans "Your Seafile client is out of date, please upgrade to latest version." %}<a href="http://www.seafile.com/download">{% trans "Click to download." %}</a></p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@@ -13,78 +13,124 @@ $('#repo-create')
|
||||
}
|
||||
);
|
||||
$('#encrypt-switch').click(function () {
|
||||
var form = $('#repo-create-form'),
|
||||
pwd_input = $('input[type="password"]', form);
|
||||
|
||||
if ($(this).attr('checked')) {
|
||||
$('#repo-create-form input[type="password"]').attr('disabled', false).removeClass('input-disabled');
|
||||
pwd_input.attr('disabled', false).removeClass('input-disabled');
|
||||
} else {
|
||||
$('#repo-create-form input[type="password"]').attr('disabled', true).addClass('input-disabled');
|
||||
pwd_input.attr('disabled', true).addClass('input-disabled');
|
||||
}
|
||||
});
|
||||
$('#repo-create-form').submit(function() {
|
||||
var passwd = $(this).find('input[name="passwd"]'),
|
||||
passwd_again = $(this).find('input[name="passwd_again"]');
|
||||
var form = $(this),
|
||||
form_id = form.attr('id'),
|
||||
name = $('#repo-name').val(),
|
||||
desc = $('#repo-desc').val(),
|
||||
encrypted = $('#encrypt-switch').attr('checked'),
|
||||
passwd, passwd_again;
|
||||
|
||||
var form = 'repo-create-form';
|
||||
if (!$.trim($('#repo-name').val())) {
|
||||
apply_form_error(form, "{% trans "Name can't be empty" %}");
|
||||
if (!$.trim(name)) {
|
||||
apply_form_error(form_id, "{% trans "Name is required" %}");
|
||||
return false;
|
||||
}
|
||||
if (!$.trim($('#repo-desc').val())) {
|
||||
apply_form_error(form, "{% trans "Description can't be empty" %}");
|
||||
if (!$.trim(desc)) {
|
||||
apply_form_error(form_id, "{% trans "Description is required" %}");
|
||||
return false;
|
||||
}
|
||||
if ($('#encrypt-switch').attr('checked')) {
|
||||
if (!$.trim(passwd.val())) {
|
||||
apply_form_error(form, "{% trans "Please enter password" %}");
|
||||
if (encrypted) {
|
||||
passwd = $('input[name="passwd"]', form).val();
|
||||
passwd_again = $('input[name="passwd_again"]', form).val();
|
||||
|
||||
if (!$.trim(passwd)) {
|
||||
apply_form_error(form_id, "{% trans "Please enter password" %}");
|
||||
return false;
|
||||
}
|
||||
if ($.trim(passwd.val()).length < 3) {
|
||||
apply_form_error(form, "{% trans "Password is too short (minimum is 3 characters)" %}");
|
||||
if ($.trim(passwd).length < 3) {
|
||||
apply_form_error(form_id, "{% trans "Password is too short (minimum is 3 characters)" %}");
|
||||
return false;
|
||||
}
|
||||
if ($.trim(passwd.val()).length > 30) {
|
||||
apply_form_error(form, "{% trans "Password is too long (maximum is 30 characters)" %}");
|
||||
if ($.trim(passwd).length > 30) {
|
||||
apply_form_error(form_id, "{% trans "Password is too long (maximum is 30 characters)" %}");
|
||||
return false;
|
||||
}
|
||||
if (!$.trim(passwd_again.val())) {
|
||||
apply_form_error(form, "{% trans "Please enter the password again" %}");
|
||||
if (!$.trim(passwd_again)) {
|
||||
apply_form_error(form_id, "{% trans "Please enter the password again" %}");
|
||||
return false;
|
||||
}
|
||||
if ($.trim(passwd.val()) != $.trim(passwd_again.val())) {
|
||||
apply_form_error(form, "{% trans "Passwords don't match" %}");
|
||||
if ($.trim(passwd) != $.trim(passwd_again)) {
|
||||
apply_form_error(form_id, "{% trans "Passwords don't match" %}");
|
||||
return false;
|
||||
}
|
||||
|
||||
{% if not keep_enc_repo_passwd %}
|
||||
// don't send the password to the server
|
||||
var salt = sjcl.codec.bytes.toBits([0xda, 0x90, 0x45, 0xc3, 0x06, 0xc7, 0xcc, 0x26]);
|
||||
var uu_id = uuid.v4();
|
||||
var magic_array = sjcl.misc.pbkdf2(uu_id + passwd, salt, 1000, 32*8, null); // 32 bytes
|
||||
var magic_str = sjcl.codec.hex.fromBits(magic_array);
|
||||
|
||||
var secret_array;
|
||||
if (window.crypto && window.crypto.getRandomValues) {
|
||||
secret_array = new Uint32Array(8);
|
||||
window.crypto.getRandomValues(secret_array);
|
||||
} else {
|
||||
secret_array = [];
|
||||
for (var i = 0; i < 8; i++) {
|
||||
secret_array.push(parseInt(Math.random() * Math.pow(2,32)));
|
||||
}
|
||||
}
|
||||
|
||||
var submit_btn = $(this).find('input[type="submit"]');
|
||||
var key_array = sjcl.misc.pbkdf2(passwd, salt, 1000, 32*8, null);
|
||||
var iv_array = sjcl.misc.pbkdf2(key_array, salt, 10, 32*8, null);
|
||||
var key = sjcl.codec.hex.fromBits(key_array);
|
||||
var iv = sjcl.codec.hex.fromBits(iv_array);
|
||||
var random_key_obj = CryptoJS.AES.encrypt(CryptoJS.lib.WordArray.create(secret_array), CryptoJS.enc.Hex.parse(key), {iv: CryptoJS.enc.Hex.parse(iv)});
|
||||
var random_key = random_key_obj.ciphertext.toString(CryptoJS.enc.Hex); // convert to hex
|
||||
{% endif %}
|
||||
}
|
||||
|
||||
var submit_btn = $('input[type="submit"]', form);
|
||||
disable(submit_btn);
|
||||
|
||||
var post_data = {
|
||||
'repo_name': name,
|
||||
'repo_desc': desc,
|
||||
'encryption': encrypted ? 1 : 0
|
||||
};
|
||||
{% if create_shared_repo %}
|
||||
$.extend(post_data, {
|
||||
'permission': $('select[name="permission"]', form).val()
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
if (encrypted) {
|
||||
{% if keep_enc_repo_passwd %}
|
||||
$.extend(post_data, {
|
||||
'passwd': passwd,
|
||||
'passwd_again': passwd_again
|
||||
});
|
||||
{% else %}
|
||||
$.extend(post_data, {
|
||||
'uuid': uu_id,
|
||||
'magic_str': magic_str,
|
||||
'random_key': random_key
|
||||
});
|
||||
{% endif %}
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: '{{ post_url }}',
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
beforeSend: prepareCSRFToken,
|
||||
data: {
|
||||
'repo_name': $('#repo-name').val(),
|
||||
'repo_desc': $('#repo-desc').val(),
|
||||
{% if create_shared_repo %}
|
||||
'permission': $('#repo-create-form select[name="permission"]').val(),
|
||||
{% endif %}
|
||||
'encryption': $('#encrypt-switch').attr('checked') ? 1 : 0,
|
||||
'passwd': passwd.val(),
|
||||
'passwd_again': passwd_again.val()
|
||||
},
|
||||
data: post_data,
|
||||
success: function(data) {
|
||||
if (data['success']) {
|
||||
location.reload(true);
|
||||
} else {
|
||||
apply_form_error('repo-create-form', data['error']);
|
||||
enable(submit_btn);
|
||||
}
|
||||
},
|
||||
error: function(data, textStatus, jqXHR) {
|
||||
var errors = $.parseJSON(data.responseText);
|
||||
$.each(errors, function(index, value) {
|
||||
apply_form_error('repo-create-form', value[0]);
|
||||
});
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
var error = $.parseJSON(xhr.responseText).error;
|
||||
apply_form_error(form_id, error);
|
||||
enable(submit_btn);
|
||||
}
|
||||
});
|
||||
|
@@ -21,7 +21,7 @@
|
||||
<td class="dirent-op">
|
||||
<div class="repo-file-op vh">
|
||||
<div class="displayed-op">
|
||||
<a class="op download" href="{% url 'repo_download_dir' repo.id %}?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}">{% trans 'Download' %}</a>
|
||||
<a class="op dir-download" href="{% url 'repo_download_dir' repo.id %}?p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}">{% trans 'Download' %}</a>
|
||||
{% if not repo.encrypted %}
|
||||
<a class="op dir-share" href="#" data-link="{{ dirent.sharelink }}" data-token="{{ dirent.sharetoken }}">{% trans "Share" %}</a>
|
||||
{% endif %}
|
||||
@@ -67,7 +67,7 @@
|
||||
<td class="dirent-op">
|
||||
<div class="repo-file-op vh">
|
||||
<div class="displayed-op">
|
||||
<a class="op download" href="{{ SITE_ROOT }}repo/{{ repo.props.id }}/{{ dirent.props.obj_id }}/?file_name={{ dirent.props.obj_name|urlencode }}&op=download">{% trans "Download"%}</a>
|
||||
<a class="op file-download" href="{{ SITE_ROOT }}repo/{{ repo.props.id }}/{{ dirent.props.obj_id }}/?file_name={{ dirent.props.obj_name|urlencode }}&op=download" data-fileid="{{ dirent.props.obj_id }}">{% trans "Download"%}</a>
|
||||
{% if user_perm == 'rw' %}
|
||||
<a class="op file-update" href="#">{% trans "Update"%}</a>
|
||||
{% endif %}
|
||||
|
@@ -67,10 +67,6 @@
|
||||
{% endif %}
|
||||
|
||||
{% if request.user.is_authenticated %}
|
||||
{% block open_local %}
|
||||
<button id="open-local" data="{{path}}">{% trans "Open local file"%}</button>
|
||||
{% endblock %}
|
||||
|
||||
{% block edit_file %}
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
@@ -89,17 +85,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="open-local-feedback" class="hide">
|
||||
<p id="open-local-handling-tip">{% trans "Processing..."%}</p>
|
||||
<p id="open-local-error" class="error"></p>
|
||||
<div id="redirect-download" class="hide">
|
||||
<p class="error">{% trans "You have not downloaded " %}"{{ repo.props.name }}"{% trans "." %} </p>
|
||||
<button data="{{ SITE_ROOT }}download/repo/?repo_id={{ repo.id }}" id="download-repo">{% trans "Click to download"%}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<iframe class="hide" id="open-local-iframe"></iframe>
|
||||
|
||||
{% include "snippets/file_share_popup.html" %}
|
||||
|
||||
{% with attach_type='file' %}
|
||||
@@ -178,78 +163,10 @@ $('#star').click(function() {
|
||||
}
|
||||
);
|
||||
|
||||
//open local
|
||||
function send_open_local_file_request(path) {
|
||||
var callback = 'xx';
|
||||
$.ajax({
|
||||
url: '{{ applet_root }}/open-local-file/?repo_id={{ repo.id }}&commit_id={{current_commit.id}}&path=' + e(path) + '&callback=' + callback,
|
||||
dataType: 'jsonp',
|
||||
jsonpCallback: callback,
|
||||
crossDomain: true,
|
||||
success: function(data) {
|
||||
$('#open-local-handling-tip').addClass('hide');
|
||||
if (data['exists'] === false) { // repo doesn't exist on local machine
|
||||
$('#open-local-error').addClass('hide');
|
||||
$('#redirect-download').removeClass('hide');
|
||||
|
||||
} else if (data['no_assoc'] === true) { // no application to open the file
|
||||
$('#open-local-error').html('{% trans "Failed to find an application to open the file. Seafile will open the folder." %}');
|
||||
|
||||
} else if (data['outdated'] === true) { // local repo not in sync yet
|
||||
if (data['auto-sync'] === false) {
|
||||
$('#open-local-error').html('{% trans "The file is not synchronized, you can synchronize it manually." %}');
|
||||
} else {
|
||||
$('#open-local-error').html('{% trans "The file is not synchronized, please retry later." %}');
|
||||
}
|
||||
|
||||
} else if (data['error']) { // other error
|
||||
$('#open-local-error').html('{% trans "An error occurred when open the local file." %}');
|
||||
|
||||
} else { // open file successfully
|
||||
$('#open-local-handling-tip').removeClass('hide');
|
||||
setTimeout(function() { $.modal.close(); }, 1500);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
$('#download-repo').click(function() {
|
||||
location.href = $(this).attr('data');
|
||||
});
|
||||
|
||||
$('#open-local').click(function () {
|
||||
var path = $(this).attr('data');
|
||||
var local_applet_running = false;
|
||||
$('#open-local-feedback').modal({appendTo: '#main', containerCss: { width: 300}});
|
||||
$('#simplemodal-container').css('height', 'auto');
|
||||
|
||||
$.ajax({
|
||||
url: '{{ applet_root }}/seafile_rpc_version/',
|
||||
dataType: 'jsonp',
|
||||
jsonpCallback: 'xx',
|
||||
crossDomain: true,
|
||||
success: function(version) {
|
||||
local_applet_running = true;
|
||||
if (version < 1) {
|
||||
$('#open-local-handling-tip').addClass('hide');
|
||||
$('#open-local-error').html('{% trans 'You are running an old version of Seafile client, please <a target="_blank">upgrade</a> it.' %}');
|
||||
$('#open-local-error a').attr('href', 'http://www.seafile.com/');
|
||||
} else {
|
||||
send_open_local_file_request(path);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var url = '{{ applet_root }}/open-local-file/?repo_id={{ repo.id }}&commit_id={{current_commit.id}}&path=' + e(path) + '&callback=xx';
|
||||
var url_short = url.slice(0, 40) + '...';
|
||||
|
||||
setTimeout(function() {
|
||||
if (!local_applet_running) {
|
||||
$('#open-local-handling-tip').addClass('hide');
|
||||
$('#open-local-error').html("{% trans 'No running Seafile client is detected. If you are sure Seafile client is running, click the following link to open the local file:' %}" + '<br/><a href="' + url + '" target="open-local-iframe">' + url_short + '</a>');
|
||||
}
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
$('#file-op .history').click(function () {
|
||||
location.href = $(this).data('url');
|
||||
});
|
||||
|
@@ -1,8 +1,6 @@
|
||||
{% extends 'view_file_base.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block open_local %}{% endblock %}
|
||||
|
||||
{% block edit_file %}
|
||||
{% if user_perm == 'rw' and not err%}
|
||||
<button data="{{ SITE_ROOT }}repo/{{ repo.id }}/file/edit/?p={{ path|urlencode }}&file_enc={{file_enc}}" id="edit">{% trans "Edit"%}</button>
|
||||
|
@@ -133,6 +133,8 @@ urlpatterns = patterns('',
|
||||
|
||||
url(r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/current_commit/$', get_current_commit, name='get_current_commit'),
|
||||
|
||||
url(r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/encrypted_file/(?P<file_id>[0-9a-f]{40})/download/$', download_enc_file, name='download_enc_file'),
|
||||
|
||||
### Apps ###
|
||||
(r'^api2/', include('seahub.api2.urls')),
|
||||
(r'^avatar/', include('seahub.avatar.urls')),
|
||||
|
@@ -89,7 +89,7 @@ if HAS_OFFICE_CONVERTER:
|
||||
import seahub.settings as settings
|
||||
from seahub.settings import FILE_PREVIEW_MAX_SIZE, INIT_PASSWD, USE_PDFJS, FILE_ENCODING_LIST, \
|
||||
FILE_ENCODING_TRY_LIST, SEND_EMAIL_ON_ADDING_SYSTEM_MEMBER, SEND_EMAIL_ON_RESETTING_USER_PASSWD, \
|
||||
ENABLE_SUB_LIBRARY
|
||||
ENABLE_SUB_LIBRARY, KEEP_ENC_REPO_PASSWD
|
||||
|
||||
# Get an instance of a logger
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -609,7 +609,8 @@ def repo_history(request, repo_id):
|
||||
raise Http404
|
||||
|
||||
password_set = False
|
||||
if repo.props.encrypted:
|
||||
if repo.props.encrypted and \
|
||||
(repo.enc_version == 1 or (repo.enc_version == 2 and KEEP_ENC_REPO_PASSWD)):
|
||||
try:
|
||||
ret = seafserv_rpc.is_passwd_set(repo_id, request.user.username)
|
||||
if ret == 1:
|
||||
@@ -617,7 +618,7 @@ def repo_history(request, repo_id):
|
||||
except SearpcError, e:
|
||||
return render_error(request, e.msg)
|
||||
|
||||
if repo.props.encrypted and not password_set:
|
||||
if not password_set:
|
||||
return HttpResponseRedirect(reverse('repo', args=[repo_id]))
|
||||
|
||||
try:
|
||||
@@ -665,7 +666,8 @@ def repo_view_snapshot(request, repo_id):
|
||||
raise Http404
|
||||
|
||||
password_set = False
|
||||
if repo.props.encrypted:
|
||||
if repo.props.encrypted and \
|
||||
(repo.enc_version == 1 or (repo.enc_version == 2 and KEEP_ENC_REPO_PASSWD)):
|
||||
try:
|
||||
ret = seafserv_rpc.is_passwd_set(repo_id, request.user.username)
|
||||
if ret == 1:
|
||||
@@ -673,7 +675,7 @@ def repo_view_snapshot(request, repo_id):
|
||||
except SearpcError, e:
|
||||
return render_error(request, e.msg)
|
||||
|
||||
if repo.props.encrypted and not password_set:
|
||||
if not password_set:
|
||||
return HttpResponseRedirect(reverse('repo', args=[repo_id]))
|
||||
|
||||
try:
|
||||
@@ -718,7 +720,8 @@ def repo_history_revert(request, repo_id):
|
||||
return render_permission_error(request, _(u'You have no permission to restore library'))
|
||||
|
||||
password_set = False
|
||||
if repo.props.encrypted:
|
||||
if repo.props.encrypted and \
|
||||
(repo.enc_version == 1 or (repo.enc_version == 2 and KEEP_ENC_REPO_PASSWD)):
|
||||
try:
|
||||
ret = seafserv_rpc.is_passwd_set(repo_id, request.user.username)
|
||||
if ret == 1:
|
||||
@@ -726,7 +729,7 @@ def repo_history_revert(request, repo_id):
|
||||
except SearpcError, e:
|
||||
return render_error(request, e.msg)
|
||||
|
||||
if repo.props.encrypted and not password_set:
|
||||
if not password_set:
|
||||
return HttpResponseRedirect(reverse('repo', args=[repo_id]))
|
||||
|
||||
commit_id = request.GET.get('commit_id', '')
|
||||
@@ -784,6 +787,9 @@ def get_diff(repo_id, arg1, arg2):
|
||||
|
||||
@login_required
|
||||
def repo_history_changes(request, repo_id):
|
||||
if not request.is_ajax():
|
||||
return Http404
|
||||
|
||||
changes = {}
|
||||
content_type = 'application/json; charset=utf-8'
|
||||
|
||||
@@ -794,7 +800,9 @@ def repo_history_changes(request, repo_id):
|
||||
if not repo:
|
||||
return HttpResponse(json.dumps(changes), content_type=content_type)
|
||||
|
||||
if repo.encrypted and not is_passwd_set(repo_id, request.user.username):
|
||||
if repo.encrypted and \
|
||||
(repo.enc_version == 1 or (repo.enc_version == 2 and KEEP_ENC_REPO_PASSWD)) \
|
||||
and not is_passwd_set(repo_id, request.user.username):
|
||||
return HttpResponse(json.dumps(changes), content_type=content_type)
|
||||
|
||||
commit_id = request.GET.get('commit_id', '')
|
||||
@@ -1093,23 +1101,41 @@ def public_repo_create(request):
|
||||
content_type = 'application/json; charset=utf-8'
|
||||
|
||||
form = SharedRepoCreateForm(request.POST)
|
||||
if form.is_valid():
|
||||
if not form.is_valid():
|
||||
result['error'] = str(form.errors.values()[0])
|
||||
return HttpResponseBadRequest(json.dumps(result),
|
||||
content_type=content_type)
|
||||
|
||||
repo_name = form.cleaned_data['repo_name']
|
||||
repo_desc = form.cleaned_data['repo_desc']
|
||||
permission = form.cleaned_data['permission']
|
||||
encryption = int(form.cleaned_data['encryption'])
|
||||
|
||||
passwd = form.cleaned_data['passwd']
|
||||
uuid = form.cleaned_data['uuid']
|
||||
magic_str = form.cleaned_data['magic_str']
|
||||
random_key = form.cleaned_data['random_key']
|
||||
user = request.user.username
|
||||
|
||||
try:
|
||||
# create a repo
|
||||
repo_id = seafserv_threaded_rpc.create_repo(repo_name, repo_desc,
|
||||
user, passwd)
|
||||
if not encryption:
|
||||
repo_id = seafile_api.create_repo(repo_name, repo_desc, user, None)
|
||||
else:
|
||||
if KEEP_ENC_REPO_PASSWD:
|
||||
repo_id = seafile_api.create_repo(repo_name, repo_desc, user, passwd)
|
||||
else:
|
||||
repo_id = seafile_api.create_enc_repo(uuid, repo_name, repo_desc, user, magic_str, random_key, enc_version=2)
|
||||
|
||||
# set this repo as inner pub
|
||||
seafserv_threaded_rpc.set_inner_pub_repo(repo_id, permission)
|
||||
except:
|
||||
seafile_api.add_inner_pub_repo(repo_id, permission)
|
||||
#seafserv_threaded_rpc.set_inner_pub_repo(repo_id, permission)
|
||||
except SearpcError, e:
|
||||
repo_id = None
|
||||
|
||||
if not repo_id:
|
||||
result['error'] = _(u'Failed to create library')
|
||||
result['error'] = _(u'Internal Server Error')
|
||||
return HttpResponse(json.dumps(result), status=500,
|
||||
content_type=content_type)
|
||||
else:
|
||||
result['success'] = True
|
||||
repo_created.send(sender=None,
|
||||
@@ -1117,11 +1143,7 @@ def public_repo_create(request):
|
||||
creator=user,
|
||||
repo_id=repo_id,
|
||||
repo_name=repo_name)
|
||||
|
||||
return HttpResponse(json.dumps(result), content_type=content_type)
|
||||
else:
|
||||
return HttpResponseBadRequest(json.dumps(form.errors),
|
||||
content_type=content_type)
|
||||
|
||||
@login_required
|
||||
def unsetinnerpub(request, repo_id):
|
||||
@@ -1267,7 +1289,9 @@ def get_repo_download_url(request, repo_id):
|
||||
url += "&email=%s&token=%s" % (email, token)
|
||||
url += "&repo_id=%s&repo_name=%s" % (repo_id, quote_repo_name)
|
||||
if enc:
|
||||
url += "&encrypted=1&magic=%s" % repo.magic
|
||||
url += "&encrypted=1&magic=%s&enc_ver=%s" % (repo.magic, repo.enc_version)
|
||||
if repo.enc_version == 2 and repo.random_key:
|
||||
url += "&key=%s" % repo.random_key
|
||||
|
||||
return url, ''
|
||||
|
||||
@@ -1355,19 +1379,34 @@ def repo_create(request):
|
||||
content_type = 'application/json; charset=utf-8'
|
||||
|
||||
form = RepoCreateForm(request.POST)
|
||||
if form.is_valid():
|
||||
if not form.is_valid():
|
||||
result['error'] = str(form.errors.values()[0])
|
||||
return HttpResponseBadRequest(json.dumps(result),
|
||||
content_type=content_type)
|
||||
|
||||
repo_name = form.cleaned_data['repo_name']
|
||||
repo_desc = form.cleaned_data['repo_desc']
|
||||
passwd = form.cleaned_data['passwd']
|
||||
user = request.user.username
|
||||
encryption = int(form.cleaned_data['encryption'])
|
||||
|
||||
passwd = form.cleaned_data['passwd']
|
||||
uuid = form.cleaned_data['uuid']
|
||||
magic_str = form.cleaned_data['magic_str']
|
||||
random_key = form.cleaned_data['random_key']
|
||||
user = request.user.username
|
||||
try:
|
||||
repo_id = seafserv_threaded_rpc.create_repo(repo_name, repo_desc,
|
||||
user, passwd)
|
||||
except:
|
||||
if not encryption:
|
||||
repo_id = seafile_api.create_repo(repo_name, repo_desc, user, None)
|
||||
else:
|
||||
if KEEP_ENC_REPO_PASSWD:
|
||||
repo_id = seafile_api.create_repo(repo_name, repo_desc, user, passwd)
|
||||
else:
|
||||
repo_id = seafile_api.create_enc_repo(uuid, repo_name, repo_desc, user, magic_str, random_key, enc_version=2)
|
||||
except SearpcError, e:
|
||||
repo_id = None
|
||||
|
||||
if not repo_id:
|
||||
result['error'] = _(u"Failed to create library")
|
||||
result['error'] = _(u"Internal Server Error")
|
||||
return HttpResponse(json.dumps(result), status=500, content_type=content_type)
|
||||
else:
|
||||
result['success'] = True
|
||||
repo_created.send(sender=None,
|
||||
@@ -1376,9 +1415,6 @@ def repo_create(request):
|
||||
repo_id=repo_id,
|
||||
repo_name=repo_name)
|
||||
return HttpResponse(json.dumps(result), content_type=content_type)
|
||||
else:
|
||||
return HttpResponseBadRequest(json.dumps(form.errors),
|
||||
content_type=content_type)
|
||||
|
||||
def render_file_revisions (request, repo_id):
|
||||
"""List all history versions of a file."""
|
||||
|
@@ -12,7 +12,7 @@ from django.utils.http import urlquote
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
import seaserv
|
||||
from seaserv import seafile_api
|
||||
from seaserv import seafile_api, seafserv_rpc
|
||||
from pysearpc import SearpcError
|
||||
|
||||
from seahub.auth.decorators import login_required
|
||||
@@ -23,7 +23,9 @@ from seahub.views.repo import get_nav_path, get_fileshare, get_dir_share_link
|
||||
import seahub.settings as settings
|
||||
from seahub.signals import repo_created
|
||||
from seahub.utils import check_filename_with_rename
|
||||
from seahub.utils import check_filename_with_rename, EMPTY_SHA1, gen_block_get_url
|
||||
from seahub.utils.star import star_file, unstar_file
|
||||
from seahub.settings import KEEP_ENC_REPO_PASSWD
|
||||
|
||||
# Get an instance of a logger
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -181,7 +183,9 @@ def list_dir(request, repo_id):
|
||||
return HttpResponse(json.dumps({'error': err_msg}),
|
||||
status=403, content_type=content_type)
|
||||
|
||||
if repo.encrypted and not seafile_api.is_password_set(repo.id, username):
|
||||
if repo.encrypted and \
|
||||
(repo.enc_version == 1 or (repo.enc_version == 2 and KEEP_ENC_REPO_PASSWD)) \
|
||||
and not seafile_api.is_password_set(repo.id, username):
|
||||
err_msg = _(u'Library is encrypted.')
|
||||
return HttpResponse(json.dumps({'error': err_msg}),
|
||||
status=403, content_type=content_type)
|
||||
@@ -245,7 +249,9 @@ def list_dir_more(request, repo_id):
|
||||
return HttpResponse(json.dumps({'error': err_msg}),
|
||||
status=403, content_type=content_type)
|
||||
|
||||
if repo.encrypted and not seafile_api.is_password_set(repo.id, username):
|
||||
if repo.encrypted and \
|
||||
(repo.enc_version == 1 or (repo.enc_version == 2 and KEEP_ENC_REPO_PASSWD)) \
|
||||
and not seafile_api.is_password_set(repo.id, username):
|
||||
err_msg = _(u'Library is encrypted.')
|
||||
return HttpResponse(json.dumps({'error': err_msg}),
|
||||
status=403, content_type=content_type)
|
||||
@@ -858,7 +864,9 @@ def get_current_commit(request, repo_id):
|
||||
return HttpResponse(json.dumps({'error': err_msg}),
|
||||
status=403, content_type=content_type)
|
||||
|
||||
if repo.encrypted and not seafile_api.is_password_set(repo.id, username):
|
||||
if repo.encrypted and \
|
||||
(repo.enc_version == 1 or (repo.enc_version == 2 and KEEP_ENC_REPO_PASSWD)) \
|
||||
and not seafile_api.is_password_set(repo.id, username):
|
||||
err_msg = _(u'Library is encrypted.')
|
||||
return HttpResponse(json.dumps({'error': err_msg}),
|
||||
status=403, content_type=content_type)
|
||||
@@ -918,3 +926,34 @@ def sub_repo(request, repo_id):
|
||||
return HttpResponse(json.dumps(result), status=500, content_type=content_type)
|
||||
|
||||
return HttpResponse(json.dumps(result), content_type=content_type)
|
||||
|
||||
def download_enc_file(request, repo_id, file_id):
|
||||
if not request.is_ajax():
|
||||
raise Http404
|
||||
|
||||
content_type = 'application/json; charset=utf-8'
|
||||
result = {}
|
||||
|
||||
op = 'downloadblks'
|
||||
blklist = []
|
||||
|
||||
if file_id == EMPTY_SHA1:
|
||||
result = { 'blklist':blklist, 'url':None, }
|
||||
return HttpResponse(json.dumps(result), content_type=content_type)
|
||||
|
||||
try:
|
||||
blks = seafile_api.list_file_by_file_id(file_id)
|
||||
except SearpcError, e:
|
||||
result['error'] = _(u'Failed to get file block list')
|
||||
return HttpResponse(json.dumps(result), content_type=content_type)
|
||||
|
||||
blklist = blks.split('\n')
|
||||
blklist = [i for i in blklist if len(i) == 40]
|
||||
token = seafserv_rpc.web_get_access_token(repo_id, file_id,
|
||||
op, request.user.username)
|
||||
url = gen_block_get_url(token, None)
|
||||
result = {
|
||||
'blklist':blklist,
|
||||
'url':url,
|
||||
}
|
||||
return HttpResponse(json.dumps(result), content_type=content_type)
|
||||
|
@@ -9,7 +9,7 @@ from django.template import RequestContext
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
import seaserv
|
||||
from seaserv import seafile_api, MAX_UPLOAD_FILE_SIZE, get_personal_groups_by_user
|
||||
from seaserv import seafserv_rpc, seafile_api, MAX_UPLOAD_FILE_SIZE, get_personal_groups_by_user
|
||||
|
||||
from seahub.auth.decorators import login_required
|
||||
from seahub.contacts.models import Contact
|
||||
@@ -20,7 +20,7 @@ from seahub.views import gen_path_link, get_user_permission, get_repo_dirents, \
|
||||
|
||||
from seahub.utils import get_ccnetapplet_root, gen_file_upload_url, \
|
||||
get_httpserver_root, gen_dir_share_link
|
||||
from seahub.settings import ENABLE_SUB_LIBRARY
|
||||
from seahub.settings import ENABLE_SUB_LIBRARY, KEEP_ENC_REPO_PASSWD
|
||||
|
||||
# Get an instance of a logger
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -111,6 +111,34 @@ def get_ajax_upload_url(request, repo_id):
|
||||
api_upload_url = get_api_upload_url(request, repo_id)
|
||||
return api_upload_url.replace('api', 'aj')
|
||||
|
||||
def get_blks_upload_url(request, repo_id):
|
||||
'''
|
||||
Get upload url for encrypted file (uploaded in blocks)
|
||||
'''
|
||||
username = request.user.username
|
||||
if get_user_permission(request, repo_id) == 'rw':
|
||||
token = seafserv_rpc.web_get_access_token(repo_id,
|
||||
'dummy',
|
||||
'upload-blks',
|
||||
request.user.username)
|
||||
return gen_file_upload_url(token, 'upload-blks-api').replace('api', 'aj')
|
||||
else:
|
||||
return ''
|
||||
|
||||
def get_blks_update_url(request, repo_id):
|
||||
'''
|
||||
Get update url for encrypted file (uploaded in blocks)
|
||||
'''
|
||||
username = request.user.username
|
||||
if get_user_permission(request, repo_id) == 'rw':
|
||||
token = seafserv_rpc.web_get_access_token(repo_id,
|
||||
'dummy',
|
||||
'update-blks',
|
||||
request.user.username)
|
||||
return gen_file_upload_url(token, 'update-blks-api').replace('api', 'aj')
|
||||
else:
|
||||
return ''
|
||||
|
||||
def get_api_update_url(request, repo_id):
|
||||
username = request.user.username
|
||||
if get_user_permission(request, repo_id) == 'rw':
|
||||
@@ -160,7 +188,9 @@ def render_repo(request, repo):
|
||||
'repo': repo,
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
if repo.encrypted and not is_password_set(repo.id, username):
|
||||
if repo.encrypted and \
|
||||
(repo.enc_version == 1 or (repo.enc_version == 2 and KEEP_ENC_REPO_PASSWD)) \
|
||||
and not is_password_set(repo.id, username):
|
||||
return render_to_response('decrypt_repo_form.html', {
|
||||
'repo': repo,
|
||||
'next': get_next_url_from_request(request) or \
|
||||
@@ -199,6 +229,11 @@ def render_repo(request, repo):
|
||||
else:
|
||||
repo_group_str = ''
|
||||
upload_url = get_upload_url(request, repo.id)
|
||||
|
||||
if repo.encrypted and repo.enc_version == 2 and not KEEP_ENC_REPO_PASSWD:
|
||||
ajax_upload_url = get_blks_upload_url(request, repo.id)
|
||||
ajax_update_url = get_blks_update_url(request, repo.id)
|
||||
else:
|
||||
ajax_upload_url = get_ajax_upload_url(request, repo.id)
|
||||
ajax_update_url = get_ajax_update_url(request, repo.id)
|
||||
fileshare = get_fileshare(repo.id, username, path)
|
||||
@@ -280,7 +315,9 @@ def repo_history_view(request, repo_id):
|
||||
'repo': repo,
|
||||
}, context_instance=RequestContext(request))
|
||||
|
||||
if repo.encrypted and not is_password_set(repo.id, username):
|
||||
if repo.encrypted and \
|
||||
(repo.enc_version == 1 or (repo.enc_version == 2 and KEEP_ENC_REPO_PASSWD)) \
|
||||
and not is_password_set(repo.id, username):
|
||||
return render_to_response('decrypt_repo_form.html', {
|
||||
'repo': repo,
|
||||
'next': get_next_url_from_request(request) or \
|
||||
|
Reference in New Issue
Block a user