Merge branch 'dapsi' into staging
commit
5282603559
|
@ -1,209 +0,0 @@
|
|||
define([
|
||||
'/bower_components/tweetnacl/nacl-fast.min.js',
|
||||
], function () {
|
||||
var Nacl = window.nacl;
|
||||
//var PARANOIA = true;
|
||||
|
||||
var plainChunkLength = 128 * 1024;
|
||||
var cypherChunkLength = 131088;
|
||||
|
||||
var computeEncryptedSize = function (bytes, meta) {
|
||||
var metasize = Nacl.util.decodeUTF8(JSON.stringify(meta)).length;
|
||||
var chunks = Math.ceil(bytes / plainChunkLength);
|
||||
return metasize + 18 + (chunks * 16) + bytes;
|
||||
};
|
||||
|
||||
var encodePrefix = function (p) {
|
||||
return [
|
||||
65280, // 255 << 8
|
||||
255,
|
||||
].map(function (n, i) {
|
||||
return (p & n) >> ((1 - i) * 8);
|
||||
});
|
||||
};
|
||||
var decodePrefix = function (A) {
|
||||
return (A[0] << 8) | A[1];
|
||||
};
|
||||
|
||||
var slice = function (A) {
|
||||
return Array.prototype.slice.call(A);
|
||||
};
|
||||
|
||||
var createNonce = function () {
|
||||
return new Uint8Array(new Array(24).fill(0));
|
||||
};
|
||||
|
||||
var increment = function (N) {
|
||||
var l = N.length;
|
||||
while (l-- > 1) {
|
||||
/* our linter suspects this is unsafe because we lack types
|
||||
but as long as this is only used on nonces, it should be safe */
|
||||
if (N[l] !== 255) { return void N[l]++; } // jshint ignore:line
|
||||
if (l === 0) { throw new Error('E_NONCE_TOO_LARGE'); }
|
||||
N[l] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
var joinChunks = function (chunks) {
|
||||
return new Blob(chunks);
|
||||
};
|
||||
|
||||
var decrypt = function (u8, key, done, progress) {
|
||||
var MAX = u8.length;
|
||||
var _progress = function (offset) {
|
||||
if (typeof(progress) !== 'function') { return; }
|
||||
progress(Math.min(1, offset / MAX));
|
||||
};
|
||||
|
||||
var nonce = createNonce();
|
||||
var i = 0;
|
||||
|
||||
var prefix = u8.subarray(0, 2);
|
||||
var metadataLength = decodePrefix(prefix);
|
||||
|
||||
var res = {
|
||||
metadata: undefined,
|
||||
};
|
||||
|
||||
var cancelled = false;
|
||||
var cancel = function () {
|
||||
cancelled = true;
|
||||
};
|
||||
|
||||
var metaBox = new Uint8Array(u8.subarray(2, 2 + metadataLength));
|
||||
|
||||
var metaChunk = Nacl.secretbox.open(metaBox, nonce, key);
|
||||
increment(nonce);
|
||||
|
||||
try {
|
||||
res.metadata = JSON.parse(Nacl.util.encodeUTF8(metaChunk));
|
||||
} catch (e) {
|
||||
return window.setTimeout(function () {
|
||||
done('E_METADATA_DECRYPTION');
|
||||
});
|
||||
}
|
||||
|
||||
if (!res.metadata) {
|
||||
return void setTimeout(function () {
|
||||
done('NO_METADATA');
|
||||
});
|
||||
}
|
||||
|
||||
var takeChunk = function (cb) {
|
||||
setTimeout(function () {
|
||||
var start = i * cypherChunkLength + 2 + metadataLength;
|
||||
var end = start + cypherChunkLength;
|
||||
i++;
|
||||
var box = new Uint8Array(u8.subarray(start, end));
|
||||
|
||||
// decrypt the chunk
|
||||
var plaintext = Nacl.secretbox.open(box, nonce, key);
|
||||
increment(nonce);
|
||||
|
||||
if (!plaintext) { return cb('DECRYPTION_ERROR'); }
|
||||
|
||||
_progress(end);
|
||||
cb(void 0, plaintext);
|
||||
});
|
||||
};
|
||||
|
||||
var chunks = [];
|
||||
|
||||
var again = function () {
|
||||
if (cancelled) { return; }
|
||||
takeChunk(function (e, plaintext) {
|
||||
if (e) {
|
||||
return setTimeout(function () {
|
||||
done(e);
|
||||
});
|
||||
}
|
||||
if (plaintext) {
|
||||
if ((2 + metadataLength + i * cypherChunkLength) < u8.length) { // not done
|
||||
chunks.push(plaintext);
|
||||
return setTimeout(again);
|
||||
}
|
||||
chunks.push(plaintext);
|
||||
res.content = joinChunks(chunks);
|
||||
return done(void 0, res);
|
||||
}
|
||||
done('UNEXPECTED_ENDING');
|
||||
});
|
||||
};
|
||||
|
||||
again();
|
||||
|
||||
return {
|
||||
cancel: cancel
|
||||
};
|
||||
};
|
||||
|
||||
// metadata
|
||||
/* { filename: 'raccoon.jpg', type: 'image/jpeg' } */
|
||||
var encrypt = function (u8, metadata, key) {
|
||||
var nonce = createNonce();
|
||||
|
||||
// encode metadata
|
||||
var plaintext = Nacl.util.decodeUTF8(JSON.stringify(metadata));
|
||||
|
||||
// if metadata is too large, drop the thumbnail.
|
||||
if (plaintext.length > 65535) {
|
||||
var temp = JSON.parse(JSON.stringify(metadata));
|
||||
delete metadata.thumbnail;
|
||||
plaintext = Nacl.util.decodeUTF8(JSON.stringify(temp));
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
var state = 0;
|
||||
var next = function (cb) {
|
||||
if (state === 2) { return void setTimeout(cb); }
|
||||
|
||||
var start;
|
||||
var end;
|
||||
var part;
|
||||
var box;
|
||||
|
||||
if (state === 0) { // metadata...
|
||||
part = new Uint8Array(plaintext);
|
||||
box = Nacl.secretbox(part, nonce, key);
|
||||
increment(nonce);
|
||||
|
||||
if (box.length > 65535) {
|
||||
return void cb('METADATA_TOO_LARGE');
|
||||
}
|
||||
var prefixed = new Uint8Array(encodePrefix(box.length)
|
||||
.concat(slice(box)));
|
||||
state++;
|
||||
|
||||
return void setTimeout(function () {
|
||||
cb(void 0, prefixed);
|
||||
});
|
||||
}
|
||||
|
||||
// encrypt the rest of the file...
|
||||
start = i * plainChunkLength;
|
||||
end = start + plainChunkLength;
|
||||
|
||||
part = u8.subarray(start, end);
|
||||
box = Nacl.secretbox(part, nonce, key);
|
||||
increment(nonce);
|
||||
i++;
|
||||
|
||||
// regular data is done
|
||||
if (i * plainChunkLength >= u8.length) { state = 2; }
|
||||
|
||||
setTimeout(function () {
|
||||
cb(void 0, box);
|
||||
});
|
||||
};
|
||||
|
||||
return next;
|
||||
};
|
||||
|
||||
return {
|
||||
decrypt: decrypt,
|
||||
encrypt: encrypt,
|
||||
joinChunks: joinChunks,
|
||||
computeEncryptedSize: computeEncryptedSize,
|
||||
};
|
||||
});
|
|
@ -5,7 +5,7 @@ define([
|
|||
var Export = {};
|
||||
|
||||
var escapeCSV = function (v) {
|
||||
if (!/("|,)/.test(v)) {
|
||||
if (!/("|,|\n|;)/.test(v)) {
|
||||
return v || '';
|
||||
}
|
||||
var value = '';
|
||||
|
@ -14,7 +14,6 @@ define([
|
|||
return value;
|
||||
};
|
||||
Export.results = function (content, answers, TYPES) {
|
||||
console.log(content, answers, TYPES);
|
||||
if (!content || !content.form) { return; }
|
||||
var csv = "";
|
||||
var form = content.form;
|
||||
|
@ -24,8 +23,8 @@ define([
|
|||
if (!obj) { return; }
|
||||
return obj.q || Messages.form_default;
|
||||
}).filter(Boolean);
|
||||
questions.unshift(Messages.form_poll_time); // "Time"
|
||||
questions.unshift(Messages.share_formView); // "Participant"
|
||||
questions.unshift(Messages.form_poll_time); // "Time"
|
||||
|
||||
questions.forEach(function (v, i) {
|
||||
if (i) { csv += ','; }
|
||||
|
@ -37,14 +36,18 @@ define([
|
|||
csv += '\n';
|
||||
var time = new Date(obj.time).toISOString();
|
||||
var msg = obj.msg || {};
|
||||
var user = msg._userdata;
|
||||
var user = msg._userdata || {};
|
||||
csv += escapeCSV(time);
|
||||
csv += ',' + escapeCSV(user.name || Messages.anonymous);
|
||||
Object.keys(form).forEach(function (key) {
|
||||
csv += ',' + escapeCSV(String(msg[key]));
|
||||
var type = form[key].type;
|
||||
if (TYPES[type] && TYPES[type].exportCSV) {
|
||||
csv += ',' + escapeCSV(TYPES[type].exportCSV(msg[key]));
|
||||
return;
|
||||
}
|
||||
csv += ',' + escapeCSV(String(msg[key] || ''));
|
||||
});
|
||||
});
|
||||
console.log(csv);
|
||||
return csv;
|
||||
};
|
||||
|
||||
|
|
|
@ -1646,6 +1646,15 @@ define([
|
|||
|
||||
return h('div.cp-form-type-poll', lines);
|
||||
},
|
||||
exportCSV: function (answer) {
|
||||
if (!answer || !answer.values) { return ''; }
|
||||
var str = '';
|
||||
Object.keys(answer.values).sort().forEach(function (k, i) {
|
||||
if (i !== 0) { str += ';'; }
|
||||
str += k.replace(';', '').replace(':', '') + ':' + answer.values[k];
|
||||
});
|
||||
return str;
|
||||
},
|
||||
icon: h('i.cptools.cptools-form-poll')
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue