diff --git a/customize.dist/pages.js b/customize.dist/pages.js
index 74c46c4ec..4eef2aa8f 100644
--- a/customize.dist/pages.js
+++ b/customize.dist/pages.js
@@ -62,7 +62,7 @@ define([
var imprintUrl = AppConfig.imprint && (typeof(AppConfig.imprint) === "boolean" ?
'/imprint.html' : AppConfig.imprint);
- Pages.versionString = "CryptPad v3.24.0 (YunnanLakeNewt)";
+ Pages.versionString = "CryptPad v3.25.0 (ZyzomysPedunculatus)";
// used for the about menu
Pages.imprintLink = AppConfig.imprint ? footLink(imprintUrl, 'imprint') : undefined;
diff --git a/lib/commands/admin-rpc.js b/lib/commands/admin-rpc.js
index 5c64b6086..595b4c6dc 100644
--- a/lib/commands/admin-rpc.js
+++ b/lib/commands/admin-rpc.js
@@ -160,9 +160,19 @@ var archiveDocument = function (Env, Server, cb, data) {
switch (id.length) {
case 32:
// TODO disconnect users from active sessions
- return void Env.msgStore.archiveChannel(id, cb);
+ return void Env.msgStore.archiveChannel(id, Util.both(cb, function (err) {
+ Env.Log.info("ARCHIVAL_CHANNEL_BY_ADMIN_RPC", {
+ channelId: id,
+ status: err? String(err): "SUCCESS",
+ });
+ }));
case 48:
- return void Env.blobStore.archive.blob(id, cb);
+ return void Env.blobStore.archive.blob(id, Util.both(cb, function (err) {
+ Env.Log.info("ARCHIVAL_BLOB_BY_ADMIN_RPC", {
+ id: id,
+ status: err? String(err): "SUCCESS",
+ });
+ }));
default:
return void cb("INVALID_ID_LENGTH");
}
@@ -178,10 +188,21 @@ var restoreArchivedDocument = function (Env, Server, cb, data) {
switch (id.length) {
case 32:
- return void Env.msgStore.restoreArchivedChannel(id, cb);
+ return void Env.msgStore.restoreArchivedChannel(id, Util.both(cb, function (err) {
+ Env.Log.info("RESTORATION_CHANNEL_BY_ADMIN_RPC", {
+ id: id,
+ status: err? String(err): 'SUCCESS',
+ });
+ }));
case 48:
- // Env.blobStore.restore.proof(userSafekey, id, cb) // XXX ....
- return void Env.blobStore.restore.blob(id, cb);
+ // FIXME this does not yet restore blob ownership
+ // Env.blobStore.restore.proof(userSafekey, id, cb)
+ return void Env.blobStore.restore.blob(id, Util.both(cb, function (err) {
+ Env.Log.info("RESTORATION_BLOB_BY_ADMIN_RPC", {
+ id: id,
+ status: err? String(err): 'SUCCESS',
+ });
+ }));
default:
return void cb("INVALID_ID_LENGTH");
}
diff --git a/lib/storage/file.js b/lib/storage/file.js
index 4fbb52b52..d890cb0b9 100644
--- a/lib/storage/file.js
+++ b/lib/storage/file.js
@@ -722,9 +722,9 @@ var unarchiveChannel = function (env, channelName, cb) {
// restore the metadata log
Fse.move(archiveMetadataPath, metadataPath, w(function (err) {
// if there's nothing to move, you're done.
- /*if (err && err.code === 'ENOENT') {
+ if (err && err.code === 'ENOENT') {
return CB();
- }*/ // XXX make sure removing this part won't break anything
+ }
// call back with an error if something goes wrong
if (err) {
w.abort();
diff --git a/www/assert/main.js b/www/assert/main.js
index c29b3bfa3..a467bfc67 100644
--- a/www/assert/main.js
+++ b/www/assert/main.js
@@ -334,6 +334,12 @@ define([
!secret.hashData.present);
}, "test support for ugly tracking query paramaters in url");
+ assert(function (cb) {
+ var url = '//cryptpad.fr/pad/#/2/pad/edit/oRE0oLCtEXusRDyin7GyLGcS/';
+ var parsed = Hash.isValidHref(url);
+ cb(!parsed);
+ }, "test that protocol relative URLs are rejected");
+
assert(function (cb) {
var keys = Block.genkeys(Nacl.randomBytes(64));
var hash = Block.getBlockHash(keys);
@@ -349,7 +355,7 @@ define([
var v3 = Hash.isValidHref('/pad');
var v4 = Hash.isValidHref('/pad/');
- var res = v1 && v2 && v3 && v4;
+ var res = Boolean(v1 && v2 && v3 && v4);
cb(res);
if (!res) {
console.log(v1, v2, v3, v4);
@@ -361,7 +367,7 @@ define([
var v3 = Hash.isValidHref('/pad#'); // Invalid
var v4 = Hash.isValidHref('/pad/#');
- var res = v1 && v2 && v3 && v4;
+ var res = Boolean(v1 && v2 && v3 && v4);
cb(res);
if (!res) {
console.log(v1, v2, v3, v4);
@@ -373,7 +379,7 @@ define([
var v3 = Hash.isValidHref('https://cryptpad.fr/pad/#67b8385b07352be53e40746d2be6ccd7XAYSuJYYqa9NfmInyHci7LNy');
var v4 = Hash.isValidHref('/pad/#/2/pad/edit/HGu0tK2od-2BBnwAz2ZNS-t4/p/embed');
- var res = v1 && v2 && v3 && v4;
+ var res = Boolean(v1 && v2 && v3 && v4);
cb(res);
if (!res) {
console.log(v1, v2, v3, v4);
diff --git a/www/common/common-hash.js b/www/common/common-hash.js
index 4f7290b81..afdecbf57 100644
--- a/www/common/common-hash.js
+++ b/www/common/common-hash.js
@@ -465,7 +465,7 @@ Version 4: Data URL when not a realtime link yet (new pad or "static" app)
if (!/^https*:\/\//.test(href)) {
// If it doesn't start with http(s), it should be a relative href
- if (!/^\//.test(href)) { return ret; }
+ if (!/^\/($|[^\/])/.test(href)) { return ret; }
idx = href.indexOf('/#');
ret.type = href.slice(1, idx);
if (idx === -1) { return ret; }
diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js
index bd9cb784a..81b202ee0 100644
--- a/www/common/common-ui-elements.js
+++ b/www/common/common-ui-elements.js
@@ -2687,7 +2687,6 @@ define([
};
- Messages.history_trimPrompt = "This document's history is very large ({0}) and it may impact the loading time. You can delete the unnecessary history.";
UIElements.displayTrimHistoryPrompt = function (common, data) {
var mb = Util.bytesToMegabytes(data.size);
var text = Messages._getKey('history_trimPrompt', [
diff --git a/www/common/media-tag.js b/www/common/media-tag.js
index 6755df5a2..86a5a8659 100644
--- a/www/common/media-tag.js
+++ b/www/common/media-tag.js
@@ -406,10 +406,7 @@ var factory = function () {
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));
});
};
diff --git a/www/common/outer/local-store.js b/www/common/outer/local-store.js
index 645493de5..95a3bd88b 100644
--- a/www/common/outer/local-store.js
+++ b/www/common/outer/local-store.js
@@ -4,7 +4,8 @@ define([
'/common/outer/cache-store.js',
'/bower_components/localforage/dist/localforage.min.js',
'/customize/application_config.js',
-], function (Constants, Hash, Cache, localForage, AppConfig) {
+ '/common/common-util.js',
+], function (Constants, Hash, Cache, localForage, AppConfig, Util) {
var LocalStore = {};
LocalStore.setThumbnail = function (key, value, cb) {
@@ -120,7 +121,7 @@ define([
return void AppConfig.customizeLogout(cb);
}
- cb = cb || function () {};
+ cb = Util.once(cb || function () {});
try {
Cache.clear(cb);
diff --git a/www/common/translations/messages.de.json b/www/common/translations/messages.de.json
index f7e9ce178..eb2e4abcb 100644
--- a/www/common/translations/messages.de.json
+++ b/www/common/translations/messages.de.json
@@ -40,7 +40,7 @@
"saved": "Gespeichert",
"synced": "Alles gespeichert",
"deleted": "Gelöscht",
- "deletedFromServer": "Pad wurde vom Server gelöscht",
+ "deletedFromServer": "Dokument zerstört",
"mustLogin": "Du musst angemeldet sein, um auf diese Seite zuzugreifen",
"disabledApp": "Diese Anwendung wurde deaktiviert. Kontaktiere den Administrator dieses CryptPads, um mehr Informationen zu erhalten.",
"realtime_unrecoverableError": "Es ist ein nicht reparierbarer Fehler aufgetreten. Klicke auf OK, um neu zu laden.",
@@ -547,7 +547,7 @@
"upload_notEnoughSpace": "Der verfügbare Speicherplatz in deinem CryptDrive reicht leider nicht für diese Datei.",
"upload_notEnoughSpaceBrief": "Unzureichender Speicherplatz",
"upload_tooLarge": "Diese Datei überschreitet die für deinen Account erlaubte maximale Größe.",
- "upload_tooLargeBrief": "Datei zu groß",
+ "upload_tooLargeBrief": "Datei überschreitet die maximale Größe von {0} MB",
"upload_choose": "Eine Datei wählen",
"upload_pending": "In der Warteschlange",
"upload_cancelled": "Abgebrochen",
@@ -1471,5 +1471,29 @@
"error_unhelpfulScriptError": "Skriptfehler: Siehe Konsole im Browser für Details",
"documentID": "Kennung des Dokuments",
"errorPopupBlocked": "Für die Funktionsweise von CryptPad ist es erforderlich, dass neue Tabs geöffnet werden können. Bitte erlaube Pop-up-Fenster in der Adressleiste deines Browsers. Diese Fenster werden niemals dafür verwendet, dir Werbung anzuzeigen.",
- "unableToDisplay": "Das Dokument kann nicht angezeigt werden. Drücke ESC, um die Seite neu zu laden."
+ "unableToDisplay": "Das Dokument kann nicht angezeigt werden. Drücke ESC, um die Seite neu zu laden. Wenn das Problem weiterhin besteht, kontaktiere bitte den Support.",
+ "mediatag_notReady": "Bitte schließe den Download ab",
+ "settings_mediatagSizeTitle": "Limit für automatisches Herunterladen",
+ "admin_archiveHint": "Ein Dokument unzugänglich machen, ohne es endgültig zu löschen. Es wird in einem Verzeichnis \"archive\" abgelegt und nach einigen Tagen gelöscht (konfigurierbar in der Konfigurationsdatei des Servers).",
+ "mediatag_loadButton": "Anhang laden",
+ "settings_mediatagSizeHint": "Maximale Größe in Megabytes (MB) für das automatische Laden von Medienelementen (Bilder, Videos, PDFs), die in Dokumenten eingebettet sind. Größere Elemente können manuell geladen werden. Gib \"-1\" ein, um Medienelemente immer automatisch zu laden.",
+ "mediatag_saveButton": "Speichern",
+ "admin_archiveInput2": "Passwort für das Dokument",
+ "admin_archiveInput": "URL des Dokuments",
+ "admin_archiveButton": "Archivieren",
+ "Offline": "Offline",
+ "download_zip": "ZIP-Datei erstellen...",
+ "fileTableHeader": "Downloads und Uploads",
+ "allowNotifications": "Benachrichtigungen erlauben",
+ "admin_unarchiveHint": "Ein zuvor archiviertes Dokument wiederherstellen",
+ "pad_mediatagOpen": "Datei öffnen",
+ "pad_mediatagShare": "Datei teilen",
+ "download_zip_file": "Datei {0}/{1}",
+ "archivedFromServer": "Dokument archiviert",
+ "restoredFromServer": "Dokument wiederhergestellt",
+ "admin_archiveInval": "Ungültiges Dokument",
+ "admin_unarchiveButton": "Wiederherstellen",
+ "admin_unarchiveTitle": "Dokumente wiederherstellen",
+ "admin_archiveTitle": "Dokumente archivieren",
+ "history_trimPrompt": "Dieses Dokument hat einen Verlauf von {0} angesammelt, was das Laden verlangsamen kann. Ziehe in Betracht, den Verlauf zu löschen, sofern er nicht benötigt wird."
}
diff --git a/www/common/translations/messages.fr.json b/www/common/translations/messages.fr.json
index 47980ee0d..72a3fad90 100644
--- a/www/common/translations/messages.fr.json
+++ b/www/common/translations/messages.fr.json
@@ -1494,5 +1494,7 @@
"admin_archiveButton": "Archiver",
"admin_archiveHint": "Rendre un document indisponible sans le supprimer définitivement. Il sera placé dans un répertoire \"archive\" et supprimé après quelques jours (configurable dans le fichier de configuration du serveur).",
"admin_archiveTitle": "Archiver les documents",
- "mediatag_loadButton": "Charger la pièce jointe"
+ "mediatag_loadButton": "Charger la pièce jointe",
+ "history_trimPrompt": "Ce document a accumulé {0} d'historique qui peut ralentir le temps de chargement. Envisagez de supprimer l'historique s'il n'est pas nécessaire.",
+ "contacts_confirmCancel": "Êtes-vous sûr de vouloir annuler votre demande de contact avec {0} ?"
}
diff --git a/www/common/translations/messages.json b/www/common/translations/messages.json
index f5acaa6c8..f07dab3e0 100644
--- a/www/common/translations/messages.json
+++ b/www/common/translations/messages.json
@@ -1494,5 +1494,7 @@
"mediatag_notReady": "Please complete the download",
"settings_mediatagSizeTitle": "Automatic download limit",
"settings_mediatagSizeHint": "Maximum size in megabytes (MB) for automatically loading media elements (images, videos, pdf) embedded into documents. Elements bigger than the specified size can be loaded manually. Use \"-1\" to always load the media elements automatically.",
- "mediatag_loadButton": "Load attachment"
+ "mediatag_loadButton": "Load attachment",
+ "history_trimPrompt": "This document has accumulated {0} of history that may slow down loading time. Consider deleting the history if it is not needed.",
+ "contacts_confirmCancel": "Are you sure you want to cancel your contact request with {0}?"
}
diff --git a/www/profile/inner.js b/www/profile/inner.js
index 3917e2b2a..375f9588c 100644
--- a/www/profile/inner.js
+++ b/www/profile/inner.js
@@ -243,7 +243,6 @@ define([
return;
}
- Messages.contacts_confirmCancel = "Are you sure you want to cancel your contact request with {0}?"; // XXX
var addCancel = function () {
var cancelButton = h('button.btn.btn-danger.cp-app-profile-friend-request', [
h('i.fa.fa-user-times'),