diff --git a/www/convert/file-crypto.js b/www/convert/file-crypto.js deleted file mode 100644 index 6a0c08816..000000000 --- a/www/convert/file-crypto.js +++ /dev/null @@ -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, - }; -}); diff --git a/www/form/export.js b/www/form/export.js index e29c6dd87..0e78d171a 100644 --- a/www/form/export.js +++ b/www/form/export.js @@ -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; }; diff --git a/www/form/inner.js b/www/form/inner.js index 23332b944..8e6b30d47 100644 --- a/www/form/inner.js +++ b/www/form/inner.js @@ -1649,6 +1649,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') }, };