merge staging into pending allow-list work

This commit is contained in:
ansuz 2020-02-21 13:52:10 -05:00
commit cac114bb52
11 changed files with 211 additions and 71 deletions

View File

@ -386,6 +386,7 @@ Meta.commands = Object.keys(commands);
Meta.createLineHandler = function (ref, errorHandler) {
ref.meta = {};
ref.index = 0;
ref.logged = {};
return function (err, line) {
if (err) {
@ -404,10 +405,15 @@ Meta.createLineHandler = function (ref, errorHandler) {
var index = ref.index++;
if (typeof(line) === 'undefined') { return; }
if (Array.isArray(line)) {
try {
handleCommand(ref.meta, line);
} catch (err2) {
var code = err2.message;
if (ref.logged[code]) { return; }
ref.logged[code] = true;
errorHandler("METADATA_COMMAND_ERR", {
error: err2.stack,
line: line,

View File

@ -1592,6 +1592,17 @@ define([
if (data.accept) { $input.attr('accept', data.accept); }
button.click(function () { $input.click(); });
break;
case 'copy':
button = $('<button>', {
'class': 'fa fa-clone cp-toolbar-icon-import',
title: Messages.makeACopy,
}).append($('<span>', {'class': 'cp-toolbar-drawer-element'}).text(Messages.makeACopy));
button
.click(common.prepareFeedback(type))
.click(function () {
sframeChan.query('EV_MAKE_A_COPY');
});
break;
case 'importtemplate':
if (!AppConfig.enableTemplates) { return; }
if (!common.isLoggedIn()) { return; }

View File

@ -543,6 +543,28 @@ define([
});
};
var fixPadMetadata = function (parsed, copy) {
var meta;
if (Array.isArray(parsed) && typeof(parsed[3]) === "object") {
meta = parsed[3].metadata; // pad
} else if (parsed.info) {
meta = parsed.info; // poll
} else {
meta = parsed.metadata;
}
if (typeof(meta) === "object") {
meta.defaultTitle = meta.title || meta.defaultTitle;
if (copy) {
meta.defaultTitle = Messages._getKey('copy_title', [meta.defaultTitle]);
}
meta.title = "";
delete meta.users;
delete meta.chat2;
delete meta.chat;
delete meta.cursor;
}
};
common.useTemplate = function (data, Crypt, cb, optsPut) {
// opts is used to overrides options for chainpad-netflux in cryptput
// it allows us to add owners and expiration time if it is a new file
@ -576,24 +598,7 @@ define([
try {
// Try to fix the title before importing the template
var parsed = JSON.parse(val);
var meta;
if (Array.isArray(parsed) && typeof(parsed[3]) === "object") {
meta = parsed[3].metadata; // pad
} else if (parsed.info) {
meta = parsed.info; // poll
} else {
meta = parsed.metadata;
}
if (typeof(meta) === "object") {
meta.defaultTitle = meta.title || meta.defaultTitle;
meta.title = "";
delete meta.users;
delete meta.chat2;
delete meta.chat;
delete meta.cursor;
if (data.chat) { meta.chat2 = data.chat; }
if (data.cursor) { meta.cursor = data.cursor; }
}
fixPadMetadata(parsed);
val = JSON.stringify(parsed);
} catch (e) {
console.log("Can't fix template title", e);
@ -608,58 +613,96 @@ define([
var data = common.fromFileData;
var parsed = Hash.parsePadUrl(data.href);
var parsed2 = Hash.parsePadUrl(currentPad.href);
var hash = parsed.hash;
var name = data.title;
var secret = Hash.getSecrets('file', hash, data.password);
var src = fileHost + Hash.getBlobPathFromHex(secret.channel);
var key = secret.keys && secret.keys.cryptKey;
var u8;
var res;
var mode;
if (parsed2.type === 'poll') { optsPut.initialState = '{}'; }
var val;
Nthen(function(waitFor) {
Util.fetch(src, waitFor(function (err, _u8) {
if (err) { return void waitFor.abort(); }
u8 = _u8;
}));
}).nThen(function (waitFor) {
require(["/file/file-crypto.js"], waitFor(function (FileCrypto) {
FileCrypto.decrypt(u8, key, waitFor(function (err, _res) {
if (err || !_res.content) { return void waitFor.abort(); }
res = _res;
}));
}));
}).nThen(function (waitFor) {
var ext = Util.parseFilename(data.title).ext;
if (!ext) {
mode = "text";
Nthen(function(_waitFor) {
// If pad, use cryptget
if (parsed.hashData && parsed.hashData.type === 'pad') {
var optsGet = {
password: data.password,
initialState: parsed.type === 'poll' ? '{}' : undefined
};
Crypt.get(parsed.hash, _waitFor(function (err, _val) {
if (err) {
_waitFor.abort();
return void cb();
}
try {
val = JSON.parse(_val);
fixPadMetadata(val, true);
} catch (e) {
_waitFor.abort();
return void cb();
}
}), optsGet);
return;
}
require(["/common/modes.js"], waitFor(function (Modes) {
Modes.list.some(function (fType) {
if (fType.ext === ext) {
mode = fType.mode;
return true;
var name = data.title;
var secret = Hash.getSecrets(parsed.type, parsed.hash, data.password);
var src = fileHost + Hash.getBlobPathFromHex(secret.channel);
var key = secret.keys && secret.keys.cryptKey;
var u8;
var res;
var mode;
// Otherwise, it's a text blob "open in code": get blob data & convert format
Nthen(function (waitFor) {
Util.fetch(src, waitFor(function (err, _u8) {
if (err) {
_waitFor.abort();
return void waitFor.abort();
}
});
}));
}).nThen(function (waitFor) {
var reader = new FileReader();
reader.addEventListener('loadend', waitFor(function (e) {
val = {
content: e.srcElement.result,
highlightMode: mode,
metadata: {
defaultTitle: name,
title: name,
type: "code",
},
};
}));
reader.readAsText(res.content);
u8 = _u8;
}));
}).nThen(function (waitFor) {
require(["/file/file-crypto.js"], waitFor(function (FileCrypto) {
FileCrypto.decrypt(u8, key, waitFor(function (err, _res) {
if (err || !_res.content) {
_waitFor.abort();
return void waitFor.abort();
}
res = _res;
}));
}));
}).nThen(function (waitFor) {
var ext = Util.parseFilename(data.title).ext;
if (!ext) {
mode = "text";
return;
}
require(["/common/modes.js"], waitFor(function (Modes) {
Modes.list.some(function (fType) {
if (fType.ext === ext) {
mode = fType.mode;
return true;
}
});
}));
}).nThen(function (waitFor) {
var reader = new FileReader();
reader.addEventListener('loadend', waitFor(function (e) {
val = {
content: e.srcElement.result,
highlightMode: mode,
metadata: {
defaultTitle: name,
title: name,
type: "code",
},
};
}));
reader.readAsText(res.content);
}).nThen(_waitFor());
}).nThen(function () {
Crypt.put(parsed2.hash, JSON.stringify(val), cb, optsPut);
Crypt.put(parsed2.hash, JSON.stringify(val), function () {
cb();
Crypt.get(parsed2.hash, function (err, val) {
console.warn(val);
});
}, optsPut);
});
};
@ -1906,6 +1949,9 @@ define([
// if a pad is created from a file
if (sessionStorage[Constants.newPadFileData]) {
common.fromFileData = JSON.parse(sessionStorage[Constants.newPadFileData]);
var _parsed1 = Hash.parsePadUrl(common.fromFileData.href);
var _parsed2 = Hash.parsePadUrl(window.location.href);
if (_parsed1.type !== _parsed2.type) { delete common.fromFileData; }
delete sessionStorage[Constants.newPadFileData];
}

View File

@ -82,6 +82,7 @@ define([
var faRename = 'fa-pencil';
var faColor = 'cptools-palette';
var faTrash = 'fa-trash';
var faCopy = 'fa-clone';
var faDelete = 'fa-eraser';
var faAccess = 'fa-unlock-alt';
var faProperties = 'fa-info-circle';
@ -436,6 +437,10 @@ define([
'data-icon': faTags,
}, Messages.fc_hashtag)),
$separator.clone()[0],
h('li', h('a.cp-app-drive-context-makeacopy.dropdown-item.cp-app-drive-context-editable', {
'tabindex': '-1',
'data-icon': faCopy,
}, Messages.makeACopy)),
h('li', h('a.cp-app-drive-context-delete.dropdown-item.cp-app-drive-context-editable', {
'tabindex': '-1',
'data-icon': faTrash,
@ -1188,6 +1193,9 @@ define([
if (!metadata || !Util.isPlainTextFile(metadata.fileType, metadata.title)) {
hide.push('openincode');
}
if (!metadata.channel || metadata.channel.length > 32) {
hide.push('makeacopy'); // Not for blobs
}
} else if ($element.is('.cp-app-drive-element-sharedf')) {
if (containsFolder) {
// More than 1 folder selected: cannot create a new subfolder
@ -1200,6 +1208,7 @@ define([
hide.push('openincode');
hide.push('hashtag');
hide.push('delete');
hide.push('makeacopy');
//hide.push('deleteowned');
} else { // it's a folder
if (containsFolder) {
@ -1214,6 +1223,7 @@ define([
hide.push('openincode');
hide.push('properties', 'access');
hide.push('hashtag');
hide.push('makeacopy');
}
// If we're in the trash, hide restore and properties for non-root elements
if (type === "trash" && path && path.length > 4) {
@ -1250,6 +1260,7 @@ define([
hide.push('share');
hide.push('savelocal');
hide.push('openincode'); // can't because of race condition
hide.push('makeacopy');
}
if (containsFolder && paths.length > 1) {
// Cannot open multiple folders
@ -1267,11 +1278,11 @@ define([
break;
case 'tree':
show = ['open', 'openro', 'openincode', 'expandall', 'collapseall',
'color', 'download', 'share', 'savelocal', 'rename', 'delete',
'deleteowned', 'removesf', 'properties', 'access', 'hashtag'];
'color', 'download', 'share', 'savelocal', 'rename', 'delete', 'makeacopy',
'deleteowned', 'removesf', 'properties', 'hashtag'];
break;
case 'default':
show = ['open', 'openro', 'share', 'openparent', 'delete', 'deleteowned', 'properties', 'access', 'hashtag'];
show = ['open', 'openro', 'share', 'openparent', 'delete', 'deleteowned', 'properties', 'access', 'hashtag', 'makeacopy'];
break;
case 'trashtree': {
show = ['empty'];
@ -3984,6 +3995,35 @@ define([
openFile(el, true);
});
}
else if ($this.hasClass('cp-app-drive-context-makeacopy')) {
if (paths.length !== 1) { return; }
el = manager.find(paths[0].path);
var _metadata = manager.getFileData(el);
var _simpleData = {
title: _metadata.filename || _metadata.title,
href: _metadata.href || _metadata.roHref,
password: _metadata.password,
channel: _metadata.channel,
};
nThen(function (waitFor) {
var path = currentPath;
if (path[0] !== ROOT) { path = [ROOT]; }
common.sessionStorage.put(Constants.newPadFileData, JSON.stringify(_simpleData), waitFor());
common.sessionStorage.put(Constants.newPadPathKey, path, waitFor());
common.sessionStorage.put(Constants.newPadTeamKey, APP.team, waitFor());
}).nThen(function () {
var parsed = Hash.parsePadUrl(_metadata.href || _metadata.roHref);
common.openURL(Hash.hashToHref('', parsed.type));
// We need to restore sessionStorage for the next time we want to create a pad from this tab
// NOTE: the 100ms timeout is to fix a race condition in firefox where sessionStorage
// would be deleted before the new tab was created
setTimeout(function () {
common.sessionStorage.put(Constants.newPadFileData, '', function () {});
common.sessionStorage.put(Constants.newPadPathKey, '', function () {});
common.sessionStorage.put(Constants.newPadTeamKey, '', function () {});
}, 100);
});
}
else if ($this.hasClass('cp-app-drive-context-openincode')) {
if (paths.length !== 1) { return; }
var p = paths[0];

View File

@ -674,6 +674,9 @@ define([
$hist.addClass('cp-hidden-if-readonly');
toolbar.$drawer.append($hist);
var $copy = common.createButton('copy', true);
toolbar.$drawer.append($copy);
if (!cpNfInner.metadataMgr.getPrivateData().isTemplate) {
var templateObj = {
rt: cpNfInner.chainpad,

View File

@ -801,6 +801,20 @@ define([
Cryptpad.saveAsTemplate(Cryptget.put, data, cb);
});
sframeChan.on('EV_MAKE_A_COPY', function () {
var data = {
channel: secret.channel,
href: currentPad.href,
password: password,
title: currentTitle
};
sessionStorage[Utils.Constants.newPadFileData] = JSON.stringify(data);
window.open(window.location.pathname);
setTimeout(function () {
delete sessionStorage[Utils.Constants.newPadFileData];
}, 100);
});
// Messaging
sframeChan.on('Q_SEND_FRIEND_REQUEST', function (data, cb) {
Cryptpad.messaging.sendFriendRequest(data, cb);

View File

@ -1297,5 +1297,17 @@
"profile_login": "Du musst dich einloggen, um diesen Benutzer zu deinen Kontakten hinzuzufügen",
"safeLinks_error": "Dieser Link gibt dir keinen Zugriff auf das Dokument",
"settings_safeLinksCheckbox": "Sichere Links aktivieren",
"settings_safeLinksTitle": "Sichere Links"
"settings_safeLinksTitle": "Sichere Links",
"settings_trimHistoryHint": "Spare Speicherplatz, indem du den Verlauf deines CryptDrives und der Benachrichtigungen löschst. Dies hat keinen Einfluss auf den Verlauf deiner Pads. Du kannst den Verlauf der Pads in deren Eigenschaften-Dialog löschen.",
"trimHistory_noHistory": "Kein Verlauf kann gelöscht werden",
"settings_trimHistoryTitle": "Verlauf löschen",
"trimHistory_currentSize": "Aktuelle Größe des Verlaufs: <b>{0}</b>",
"trimHistory_needMigration": "Bitte <a>aktualisiere dein CryptDrive</a>, um diese Funktion zu aktivieren.",
"trimHistory_success": "Verlauf wurde gelöscht",
"trimHistory_error": "Fehler beim Löschen des Verlaufs",
"trimHistory_getSizeError": "Bei der Berechnung der Größe des Verlaufs deines CryptDrives ist ein Fehler aufgetreten",
"trimHistory_button": "Verlauf löschen",
"historyTrim_contentsSize": "Inhalte: {0}",
"historyTrim_historySize": "Verlauf: {0}",
"areYouSure": "Bist du sicher?"
}

View File

@ -1309,5 +1309,7 @@
"trimHistory_button": "Effacer l'historique",
"historyTrim_contentsSize": "Contenu : {0}",
"historyTrim_historySize": "Historique : {0}",
"areYouSure": "Êtes-vous sûr ?"
"areYouSure": "Êtes-vous sûr ?",
"copy_title": "{0} (copie)",
"makeACopy": "Créer une copie"
}

View File

@ -537,5 +537,6 @@
}
}
},
"whatis_zeroknowledge_p2": "Quando ti registri e accedi, il tuo nome utente e la tua password vengono computati in una chiave segreta utilizzando la <a href=\"https://en.wikipedia.org/wiki/Scrypt\">funzione di derivazione scrypt</a>. Ne questa chiave, ne il tuo nome utente o la tua password vengono inviati al server. Infatti sono usati soltanto dal lato client per decriptare il contenuto del tuo CryptDrive, che contiene le chiavi per tutti i pad a cui hai accesso."
"whatis_zeroknowledge_p2": "Quando ti registri e accedi, il tuo nome utente e la tua password vengono computati in una chiave segreta utilizzando la <a href=\"https://en.wikipedia.org/wiki/Scrypt\">funzione di derivazione scrypt</a>. Ne questa chiave, ne il tuo nome utente o la tua password vengono inviati al server. Infatti sono usati soltanto dal lato client per decriptare il contenuto del tuo CryptDrive, che contiene le chiavi per tutti i pad a cui hai accesso.",
"faq_title": "Domande frequenti"
}

View File

@ -1309,5 +1309,7 @@
"trimHistory_currentSize": "Current history size: <b>{0}</b>",
"trimHistory_noHistory": "No history can be deleted",
"settings_trimHistoryTitle": "Delete History",
"settings_trimHistoryHint": "Save storage space by deleting the history of your drive and notifications. This will not affect the history of your pads. You can delete the history of pads in their properties dialog."
"settings_trimHistoryHint": "Save storage space by deleting the history of your drive and notifications. This will not affect the history of your pads. You can delete the history of pads in their properties dialog.",
"makeACopy": "Make a copy",
"copy_title": "{0} (copy)"
}

View File

@ -1186,6 +1186,9 @@ define([
$rightside.append($templateButton);
}
var $copy = common.createButton('copy', true);
$drawer.append($copy);
/* add an export button */
var $export = common.createButton('export', true, {}, exportFile);
$drawer.append($export);