diff --git a/customize.dist/ckeditor-contents.css b/customize.dist/ckeditor-contents.css
index a7939839d..663cd8cb9 100644
--- a/customize.dist/ckeditor-contents.css
+++ b/customize.dist/ckeditor-contents.css
@@ -232,14 +232,35 @@ media-tag button.btn {
transition: none;
color: #3F4141;
border: 1px solid #3F4141;
+ max-width: 250px;
}
+media-tag button.mediatag-download-btn {
+ flex-flow: column;
+ min-height: 38px;
+ justify-content: center;
+}
+media-tag button.mediatag-download-btn > span {
+ display: flex;
+ line-height: 1.5;
+ align-items: center;
+ justify-content: center;
+}
+media-tag button.mediatag-download-btn * {
+ width: auto;
+}
+media-tag button.mediatag-download-btn > span.mediatag-download-name b {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
media-tag button.btn:hover, media-tag button.btn:active, media-tag button.btn:focus {
background-color: #ccc;
}
-media-tag button b {
+media-tag button.btn b {
margin-left: 5px;
}
-media-tag button .fa {
+media-tag button.btn .fa {
display: inline;
margin-right: 5px;
}
diff --git a/customize.dist/src/less2/include/markdown.less b/customize.dist/src/less2/include/markdown.less
index d7fe13f43..af3ac74d8 100644
--- a/customize.dist/src/less2/include/markdown.less
+++ b/customize.dist/src/less2/include/markdown.less
@@ -94,8 +94,24 @@
height: 80vh;
max-height: 90vh;
}
+ button.mediatag-download-btn {
+ flex-flow: column;
+ & > span {
+ display: flex;
+ line-height: 1.5;
+ align-items: center;
+ &.mediatag-download-name b {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ }
+ }
button.btn-default {
display: inline-flex;
+ max-width: 250px;
+ min-height: 38px;
+ justify-content: center;
.fa {
margin-right: 5px;
}
diff --git a/www/common/inner/common-mediatag.js b/www/common/inner/common-mediatag.js
index 72cb1e37b..eaf640b0d 100644
--- a/www/common/inner/common-mediatag.js
+++ b/www/common/inner/common-mediatag.js
@@ -23,9 +23,10 @@ define([
viewer: '/common/pdfjs/web/viewer.html'
});
Messages.mediatag_saveButton = "Save"; // XXX
+ Messages.mediatag_loadButton = "Load attachment"; // XXX
MediaTag.setDefaultConfig('download', {
text: Messages.mediatag_saveButton,
- textDl: Messages.download_mt_button,
+ textDl: Messages.mediatag_loadButton,
});
}
MT.MediaTag = MediaTag;
diff --git a/www/common/media-tag.js b/www/common/media-tag.js
index 8f7276446..446dfdf08 100644
--- a/www/common/media-tag.js
+++ b/www/common/media-tag.js
@@ -181,14 +181,17 @@ var factory = function () {
mediaObject.tag.appendChild(text);
};
var makeDownloadButton = function (cfg, mediaObject, size, cb) {
+ var metadata = cfg.metadata || {};
+ var i = '';
+ var name = metadata.name ? ''+ i +''+
+ fixHTML(metadata.name)+'' : '';
var btn = document.createElement('button');
- btn.setAttribute('class', 'btn btn-default');
- btn.setAttribute('data-dl', '1');
- btn.innerHTML = '' +
- cfg.download.textDl + ' (' + size + 'MB)';
+ btn.setAttribute('class', 'btn btn-default mediatag-download-btn');
+ btn.innerHTML = name + '' + (name ? '' : i) +
+ cfg.download.textDl + ' (' + size + 'MB)';
btn.addEventListener('click', function () {
makeProgressBar(cfg, mediaObject);
- var a = (cfg.body || document).querySelectorAll('media-tag[src="'+mediaObject.tag.getAttribute('src')+'"] button[data-dl]');
+ var a = (cfg.body || document).querySelectorAll('media-tag[src="'+mediaObject.tag.getAttribute('src')+'"] button.mediatag-download-btn');
for(var i = 0; i < a.length; i++) {
if (a[i] !== btn) { a[i].click(); }
}
@@ -346,6 +349,95 @@ var factory = function () {
}
};
+ // The metadata size can go up to 65535 (16 bits - 2 bytes)
+ // The first 8 bits are stored in A[0]
+ // The last 8 bits are stored in A[0]
+ var uint8ArrayJoin = function (AA) {
+ var l = 0;
+ var i = 0;
+ for (; i < AA.length; i++) { l += AA[i].length; }
+ var C = new Uint8Array(l);
+
+ i = 0;
+ for (var offset = 0; i < AA.length; i++) {
+ C.set(AA[i], offset);
+ offset += AA[i].length;
+ }
+ return C;
+ };
+ var fetchMetadata = function (src, _cb) {
+ var cb = function (e, res) {
+ _cb(e, res);
+ cb = function () {};
+ };
+
+ var cacheKey = getCacheKey(src);
+
+ var fetch = function () {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', src, true);
+ xhr.setRequestHeader('Range', 'bytes=0-1');
+ xhr.responseType = 'arraybuffer';
+
+ xhr.onerror = function () { return void cb("XHR_ERROR"); };
+ xhr.onload = function () {
+ // Error?
+ if (/^4/.test('' + this.status)) { return void cb("XHR_ERROR " + this.status); }
+ var res = new Uint8Array(xhr.response);
+ var size = Decrypt.decodePrefix(res);
+ var xhr2 = new XMLHttpRequest();
+
+ xhr2.open("GET", src, true);
+ xhr2.setRequestHeader('Range', 'bytes=2-' + (size + 2));
+ xhr2.responseType = 'arraybuffer';
+ xhr2.onload = function () {
+ if (/^4/.test('' + this.status)) { return void cb("XHR_ERROR " + this.status); }
+ var res2 = new Uint8Array(xhr2.response);
+ var all = uint8ArrayJoin([res, res2]);
+ cb(void 0, all);
+ };
+ xhr2.send(null);
+ };
+
+ xhr.send(null);
+ };
+
+ if (!cacheKey) { return void fetch(); }
+
+ getBlobCache(cacheKey, function (err, u8) {
+ if (err || !u8) { return void fetch(); }
+
+ var size = Decrypt.decodePrefix(u8.subarray(0,2));
+ console.error(size);
+
+ cb(null, u8.subarray(0, size+2));
+ });
+ };
+ var decryptMetadata = function (u8, key) {
+ var prefix = u8.subarray(0, 2);
+ var metadataLength = Decrypt.decodePrefix(prefix);
+
+ var metaBox = new Uint8Array(u8.subarray(2, 2 + metadataLength));
+ var metaChunk = window.nacl.secretbox.open(metaBox, Decrypt.createNonce(), key);
+
+ try {
+ return JSON.parse(window.nacl.util.encodeUTF8(metaChunk));
+ }
+ catch (e) { return null; }
+ };
+ var fetchDecryptedMetadata = function (src, strKey, cb) {
+ if (typeof(src) !== 'string') {
+ return window.setTimeout(function () {
+ cb('NO_SOURCE');
+ });
+ }
+ fetchMetadata(src, function (e, buffer) {
+ if (e) { return cb(e); }
+ var key = Decrypt.getKeyFromStr(strKey);
+ cb(void 0, decryptMetadata(buffer, key));
+ });
+ };
+
// Decrypts a Uint8Array with the given key.
var decrypt = function (u8, strKey, done, progressCb) {
var Nacl = window.nacl;
@@ -608,6 +700,7 @@ var factory = function () {
if (errDecryption) {
return void reject(errDecryption);
}
+ // XXX emit 'metadata' u8Decrypted.metadata
// Cache and display the decrypted blob
resolve(u8Decrypted);
}, function (progress) {
@@ -654,7 +747,12 @@ var factory = function () {
return void dl();
}
var sizeMb = Math.round(10 * size / 1024 / 1024) / 10;
- makeDownloadButton(cfg, mediaObject, sizeMb, dl);
+ fetchDecryptedMetadata(src, strKey, function (err, md) {
+ if (err) { return void error(err); }
+ cfg.metadata = md;
+ // XXX emit 'metadata'
+ makeDownloadButton(cfg, mediaObject, sizeMb, dl);
+ });
});
return mediaObject;