Browse Source

Added the possibility to generate a blockchain proof of existence

Former-commit-id: 02ad83f7343f5a270cb1c3052f0bcf1aebd9a13e
Gildas 6 years ago
parent
commit
dcba507055

+ 4 - 0
_locales/de/messages.json

@@ -383,6 +383,10 @@
 		"message": "In die Zwischenablage speichern",
 		"message": "In die Zwischenablage speichern",
 		"description": "Options page label: 'save to clipboard'"
 		"description": "Options page label: 'save to clipboard'"
 	},
 	},
+	"optionAddProof": {
+		"message": "Existenzberechtigung hinzufügen",
+		"description": "Options page label: 'add proof of existence'"
+	},
 	"optionSaveToGDrive": {
 	"optionSaveToGDrive": {
 		"message": "In Google Drive speichern",
 		"message": "In Google Drive speichern",
 		"description": "Options page label: 'save to Google Drive'"
 		"description": "Options page label: 'save to Google Drive'"

+ 4 - 0
_locales/en/messages.json

@@ -383,6 +383,10 @@
 		"message": "save to clipboard",
 		"message": "save to clipboard",
 		"description": "Options page label: 'save to clipboard'"
 		"description": "Options page label: 'save to clipboard'"
 	},
 	},
+	"optionAddProof": {
+		"message": "add proof of existence",
+		"description": "Options page label: 'add proof of existence'"
+	},
 	"optionSaveToGDrive": {
 	"optionSaveToGDrive": {
 		"message": "save to Google Drive",
 		"message": "save to Google Drive",
 		"description": "Options page label: 'save to Google Drive'"
 		"description": "Options page label: 'save to Google Drive'"

+ 4 - 0
_locales/es/messages.json

@@ -383,6 +383,10 @@
 		"message": "guardar en el portapapeles",
 		"message": "guardar en el portapapeles",
 		"description": "Options page label: 'save to clipboard'"
 		"description": "Options page label: 'save to clipboard'"
 	},
 	},
+	"optionAddProof": {
+		"message": "añadir prueba de existencia",
+		"description": "Options page label: 'add proof of existence'"
+	},
 	"optionSaveToGDrive": {
 	"optionSaveToGDrive": {
 		"message": "save en Google Drive",
 		"message": "save en Google Drive",
 		"description": "Options page label: 'save to Google Drive'"
 		"description": "Options page label: 'save to Google Drive'"

+ 4 - 0
_locales/fr/messages.json

@@ -383,6 +383,10 @@
 		"message": "sauvegarder dans le presse-papiers",
 		"message": "sauvegarder dans le presse-papiers",
 		"description": "Options page label: 'save to clipboard'"
 		"description": "Options page label: 'save to clipboard'"
 	},
 	},
+	"optionAddProof": {
+		"message": "ajouter une preuve d'existence",
+		"description": "Options page label: 'add proof of existence'"
+	},
 	"optionSaveToGDrive": {
 	"optionSaveToGDrive": {
 		"message": "sauvegarder dans Google Drive",
 		"message": "sauvegarder dans Google Drive",
 		"description": "Options page label: 'save to Google Drive'"
 		"description": "Options page label: 'save to Google Drive'"

+ 4 - 0
_locales/ja/messages.json

@@ -383,6 +383,10 @@
 		"message": "クリップボードに保存する",
 		"message": "クリップボードに保存する",
 		"description": "Options page label: 'save to clipboard'"
 		"description": "Options page label: 'save to clipboard'"
 	},
 	},
+	"optionAddProof": {
+		"message": "add proof of existence",
+		"description": "Options page label: 'add proof of existence'"
+	},
 	"optionSaveToGDrive": {
 	"optionSaveToGDrive": {
 		"message": "Google Drive に保存",
 		"message": "Google Drive に保存",
 		"description": "Options page label: 'save to Google Drive'"
 		"description": "Options page label: 'save to Google Drive'"

+ 4 - 0
_locales/pl/messages.json

@@ -383,6 +383,10 @@
 		"message": "zapisuj do schowka",
 		"message": "zapisuj do schowka",
 		"description": "Options page label: 'save to clipboard'"
 		"description": "Options page label: 'save to clipboard'"
 	},
 	},
+	"optionAddProof": {
+		"message": "add proof of existence",
+		"description": "Options page label: 'add proof of existence'"
+	},
 	"optionSaveToGDrive": {
 	"optionSaveToGDrive": {
 		"message": "zapisuj na Dysku Google",
 		"message": "zapisuj na Dysku Google",
 		"description": "Options page label: 'save to Google Drive'"
 		"description": "Options page label: 'save to Google Drive'"

+ 4 - 0
_locales/ru/messages.json

@@ -383,6 +383,10 @@
 		"message": "сохранить в буфер обмена",
 		"message": "сохранить в буфер обмена",
 		"description": "Options page label: 'save to clipboard'"
 		"description": "Options page label: 'save to clipboard'"
 	},
 	},
+	"optionAddProof": {
+		"message": "add proof of existence",
+		"description": "Options page label: 'add proof of existence'"
+	},
 	"optionSaveToGDrive": {
 	"optionSaveToGDrive": {
 		"message": "сохранить на Google Drive",
 		"message": "сохранить на Google Drive",
 		"description": "Options page label: 'save to Google Drive'"
 		"description": "Options page label: 'save to Google Drive'"

+ 4 - 0
_locales/uk/messages.json

@@ -383,6 +383,10 @@
 		"message": "зберегти в буфер обміну",
 		"message": "зберегти в буфер обміну",
 		"description": "Options page label: 'save to clipboard'"
 		"description": "Options page label: 'save to clipboard'"
 	},
 	},
+	"optionAddProof": {
+		"message": "add proof of existence",
+		"description": "Options page label: 'add proof of existence'"
+	},
 	"optionSaveToGDrive": {
 	"optionSaveToGDrive": {
 		"message": "save to Google Drive",
 		"message": "save to Google Drive",
 		"description": "Options page label: 'save to Google Drive'"
 		"description": "Options page label: 'save to Google Drive'"

+ 4 - 0
_locales/zh_CN/messages.json

@@ -383,6 +383,10 @@
 		"message": "保存到剪切板",
 		"message": "保存到剪切板",
 		"description": "Options page label: 'save to clipboard'"
 		"description": "Options page label: 'save to clipboard'"
 	},
 	},
+	"optionAddProof": {
+		"message": "add proof of existence",
+		"description": "Options page label: 'add proof of existence'"
+	},
 	"optionSaveToGDrive": {
 	"optionSaveToGDrive": {
 		"message": "save to Google Drive",
 		"message": "save to Google Drive",
 		"description": "Options page label: 'save to Google Drive'"
 		"description": "Options page label: 'save to Google Drive'"

+ 4 - 0
_locales/zh_TW/messages.json

@@ -383,6 +383,10 @@
 		"message": "保存到剪切板",
 		"message": "保存到剪切板",
 		"description": "Options page label: 'save to clipboard'"
 		"description": "Options page label: 'save to clipboard'"
 	},
 	},
+	"optionAddProof": {
+		"message": "add proof of existence",
+		"description": "Options page label: 'add proof of existence'"
+	},
 	"optionSaveToGDrive": {
 	"optionSaveToGDrive": {
 		"message": "save to Google Drive",
 		"message": "save to Google Drive",
 		"description": "Options page label: 'save to Google Drive'"
 		"description": "Options page label: 'save to Google Drive'"

+ 4 - 1
extension/core/bg/autosave.js

@@ -21,7 +21,7 @@
  *   Source.
  *   Source.
  */
  */
 
 
-/* global singlefile, URL, Blob */
+/* global singlefile, URL, Blob, woleet */
 
 
 singlefile.extension.core.bg.autosave = (() => {
 singlefile.extension.core.bg.autosave = (() => {
 
 
@@ -129,6 +129,9 @@ singlefile.extension.core.bg.autosave = (() => {
 				pageData.url = URL.createObjectURL(blob);
 				pageData.url = URL.createObjectURL(blob);
 				await singlefile.extension.core.bg.downloads.downloadPage(pageData, options);
 				await singlefile.extension.core.bg.downloads.downloadPage(pageData, options);
 			}
 			}
+			if (pageData.hash) {
+				await woleet.anchor(pageData.hash);
+			}
 		} finally {
 		} finally {
 			singlefile.extension.core.bg.business.onSaveEnd(message.taskId);
 			singlefile.extension.core.bg.business.onSaveEnd(message.taskId);
 			if (pageData && pageData.url) {
 			if (pageData && pageData.url) {

+ 1 - 0
extension/core/bg/config.js

@@ -78,6 +78,7 @@ singlefile.extension.core.bg.config = (() => {
 		groupDuplicateImages: true,
 		groupDuplicateImages: true,
 		saveRawPage: false,
 		saveRawPage: false,
 		saveToClipboard: false,
 		saveToClipboard: false,
+		addProof: false,
 		saveToGDrive: false,
 		saveToGDrive: false,
 		forceWebAuthFlow: false,
 		forceWebAuthFlow: false,
 		extractAuthCode: true,
 		extractAuthCode: true,

+ 4 - 1
extension/core/bg/downloads.js

@@ -21,7 +21,7 @@
  *   Source.
  *   Source.
  */
  */
 
 
-/* global browser, singlefile, Blob, URL, document, GDrive */
+/* global browser, singlefile, Blob, URL, document, GDrive, woleet */
 
 
 singlefile.extension.core.bg.downloads = (() => {
 singlefile.extension.core.bg.downloads = (() => {
 
 
@@ -60,6 +60,9 @@ singlefile.extension.core.bg.downloads = (() => {
 			return {};
 			return {};
 		}
 		}
 		if (message.method.endsWith(".end")) {
 		if (message.method.endsWith(".end")) {
+			if (message.hash) {
+				await woleet.anchor(message.hash);
+			}
 			singlefile.extension.core.bg.business.onSaveEnd(message.taskId);
 			singlefile.extension.core.bg.business.onSaveEnd(message.taskId);
 			return {};
 			return {};
 		}
 		}

+ 51 - 0
extension/lib/woleet/woleet.js

@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010-2019 Gildas Lormeau
+ * contact : gildas.lormeau <at> gmail.com
+ * 
+ * This file is part of SingleFile.
+ *
+ *   The code in this file is free software: you can redistribute it and/or 
+ *   modify it under the terms of the GNU Affero General Public License 
+ *   (GNU AGPL) as published by the Free Software Foundation, either version 3
+ *   of the License, or (at your option) any later version.
+ * 
+ *   The code in this file is distributed in the hope that it will be useful, 
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of 
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero 
+ *   General Public License for more details.
+ *
+ *   As additional permission under GNU AGPL version 3 section 7, you may 
+ *   distribute UNMODIFIED VERSIONS OF THIS file without the copy of the GNU 
+ *   AGPL normally required by section 4, provided you include this license 
+ *   notice and a URL through which recipients can access the Corresponding 
+ *   Source.
+ */
+
+/* global fetch */
+
+this.woleet = this.woleet || (() => {
+
+	const urlService = "https://api.woleet.io/v1/anchor";
+	const apiKey = "__WOLEET_API_KEY__";
+
+	return {
+		anchor
+	};
+
+	async function anchor(hash) {
+		return (await fetch(urlService, {
+			method: "POST",
+			headers: {
+				"Accept": "application/json",
+				"Content-Type": "application/json",
+				"Authorization": "Bearer " + apiKey
+			},
+			body: JSON.stringify({
+				"name": hash,
+				"hash": hash,
+				"public": true
+			})
+		})).json();
+	}
+
+})();

+ 5 - 0
extension/ui/bg/ui-options.js

@@ -36,6 +36,7 @@
 	const removeScriptsLabel = document.getElementById("removeScriptsLabel");
 	const removeScriptsLabel = document.getElementById("removeScriptsLabel");
 	const saveRawPageLabel = document.getElementById("saveRawPageLabel");
 	const saveRawPageLabel = document.getElementById("saveRawPageLabel");
 	const saveToClipboardLabel = document.getElementById("saveToClipboardLabel");
 	const saveToClipboardLabel = document.getElementById("saveToClipboardLabel");
+	const addProofLabel = document.getElementById("addProofLabel");
 	const saveToGDriveLabel = document.getElementById("saveToGDriveLabel");
 	const saveToGDriveLabel = document.getElementById("saveToGDriveLabel");
 	const compressHTMLLabel = document.getElementById("compressHTMLLabel");
 	const compressHTMLLabel = document.getElementById("compressHTMLLabel");
 	const compressCSSLabel = document.getElementById("compressCSSLabel");
 	const compressCSSLabel = document.getElementById("compressCSSLabel");
@@ -106,6 +107,7 @@
 	const removeScriptsInput = document.getElementById("removeScriptsInput");
 	const removeScriptsInput = document.getElementById("removeScriptsInput");
 	const saveRawPageInput = document.getElementById("saveRawPageInput");
 	const saveRawPageInput = document.getElementById("saveRawPageInput");
 	const saveToClipboardInput = document.getElementById("saveToClipboardInput");
 	const saveToClipboardInput = document.getElementById("saveToClipboardInput");
+	const addProofInput = document.getElementById("addProofInput");
 	const saveToGDriveInput = document.getElementById("saveToGDriveInput");
 	const saveToGDriveInput = document.getElementById("saveToGDriveInput");
 	const compressHTMLInput = document.getElementById("compressHTMLInput");
 	const compressHTMLInput = document.getElementById("compressHTMLInput");
 	const compressCSSInput = document.getElementById("compressCSSInput");
 	const compressCSSInput = document.getElementById("compressCSSInput");
@@ -403,6 +405,7 @@
 	removeScriptsLabel.textContent = browser.i18n.getMessage("optionRemoveScripts");
 	removeScriptsLabel.textContent = browser.i18n.getMessage("optionRemoveScripts");
 	saveRawPageLabel.textContent = browser.i18n.getMessage("optionSaveRawPage");
 	saveRawPageLabel.textContent = browser.i18n.getMessage("optionSaveRawPage");
 	saveToClipboardLabel.textContent = browser.i18n.getMessage("optionSaveToClipboard");
 	saveToClipboardLabel.textContent = browser.i18n.getMessage("optionSaveToClipboard");
+	addProofLabel.textContent = browser.i18n.getMessage("optionAddProof");
 	saveToGDriveLabel.textContent = browser.i18n.getMessage("optionSaveToGDrive");
 	saveToGDriveLabel.textContent = browser.i18n.getMessage("optionSaveToGDrive");
 	compressHTMLLabel.textContent = browser.i18n.getMessage("optionCompressHTML");
 	compressHTMLLabel.textContent = browser.i18n.getMessage("optionCompressHTML");
 	compressCSSLabel.textContent = browser.i18n.getMessage("optionCompressCSS");
 	compressCSSLabel.textContent = browser.i18n.getMessage("optionCompressCSS");
@@ -578,6 +581,7 @@
 		saveRawPageInput.checked = profileOptions.saveRawPage;
 		saveRawPageInput.checked = profileOptions.saveRawPage;
 		saveToClipboardInput.checked = profileOptions.saveToClipboard && !profileOptions.saveToGDrive;
 		saveToClipboardInput.checked = profileOptions.saveToClipboard && !profileOptions.saveToGDrive;
 		saveToClipboardInput.disabled = profileOptions.saveToGDrive;
 		saveToClipboardInput.disabled = profileOptions.saveToGDrive;
+		addProofInput.checked = profileOptions.addProof;
 		saveToGDriveInput.checked = profileOptions.saveToGDrive && !profileOptions.saveToClipboard;
 		saveToGDriveInput.checked = profileOptions.saveToGDrive && !profileOptions.saveToClipboard;
 		saveToGDriveInput.disabled = profileOptions.saveToClipboard;
 		saveToGDriveInput.disabled = profileOptions.saveToClipboard;
 		compressHTMLInput.checked = profileOptions.compressHTML;
 		compressHTMLInput.checked = profileOptions.compressHTML;
@@ -650,6 +654,7 @@
 				removeScripts: removeScriptsInput.checked,
 				removeScripts: removeScriptsInput.checked,
 				saveRawPage: saveRawPageInput.checked,
 				saveRawPage: saveRawPageInput.checked,
 				saveToClipboard: saveToClipboardInput.checked,
 				saveToClipboard: saveToClipboardInput.checked,
+				addProof: addProofInput.checked,
 				saveToGDrive: saveToGDriveInput.checked,
 				saveToGDrive: saveToGDriveInput.checked,
 				compressHTML: compressHTMLInput.checked,
 				compressHTML: compressHTMLInput.checked,
 				compressCSS: compressCSSInput.checked,
 				compressCSS: compressCSSInput.checked,

+ 29 - 0
extension/ui/pages/help.html

@@ -369,6 +369,35 @@
 							computer. Checking this option will force the "File name" options to be disabled.</p>
 							computer. Checking this option will force the "File name" options to be disabled.</p>
 						<p class="notice">It is recommended to <u>uncheck</u> this option</p>
 						<p class="notice">It is recommended to <u>uncheck</u> this option</p>
 					</li>
 					</li>
+					<li data-options-label="addProofLabel"> <span class="option">Option: add proof od existence</span>
+						<p>Check this option to create a worldwide proof of the existence of the page you want to save.
+						</p>
+						<ul>
+							<li>
+								<strong>What is a proof of existence (data anchoring)?</strong><br>
+								Data anchoring consists in building a time-stamped proof of existence for a data by
+								linking it to a tamper resistant and time-stamped blockchain. Data anchoring
+								implementation relies on the resilience and immutability of the Bitcoin blockchain
+								to provide the best possible security level
+							</li>
+							<li>
+								<strong>How does this protect my data?</strong><br>
+								The anchoring mechanism only handles data impressions. Your data remains where you
+								calculate the fingerprints, i.e. in the browser. Their confidentiality is totally
+								preserved.
+							</li>
+							<li>
+								<strong>
+									The day after your backup you can get freely the proof receipt here: <a
+										href="https://gildas-lormeau.github.io/singlefile-woleet/index.html">gildas-lormeau.github.io/singlefile-woleet/index.html</a>.
+									A proof receipt will be used to verify the validity of the evidence
+								</strong>
+							</li>
+						</ul>
+						<p>
+							More information <a href="https://doc.woleet.io">doc.woleet.io</a>
+						</p>
+					</li>
 					<li data-options-label="saveToGDriveLabel"> <span class="option">Option: save to Google Drive</span>
 					<li data-options-label="saveToGDriveLabel"> <span class="option">Option: save to Google Drive</span>
 						<p>Check this option to save the page on Google Drive instead of downloading it on your
 						<p>Check this option to save the page on Google Drive instead of downloading it on your
 							computer. Checking this option will force some "File name" options to be disabled.
 							computer. Checking this option will force some "File name" options to be disabled.

+ 4 - 0
extension/ui/pages/options.html

@@ -214,6 +214,10 @@
 				<label for="saveToClipboardInput" id="saveToClipboardLabel"></label>
 				<label for="saveToClipboardInput" id="saveToClipboardLabel"></label>
 				<input type="checkbox" id="saveToClipboardInput">
 				<input type="checkbox" id="saveToClipboardInput">
 			</div>
 			</div>
+			<div class="option">
+				<label for="addProofInput" id="addProofLabel"></label>
+				<input type="checkbox" id="addProofInput">
+			</div>
 			<div class="option">
 			<div class="option">
 				<label for="saveToGDriveInput" id="saveToGDriveLabel"></label>
 				<label for="saveToGDriveInput" id="saveToGDriveLabel"></label>
 				<input type="checkbox" id="saveToGDriveInput">
 				<input type="checkbox" id="saveToGDriveInput">

+ 2 - 1
manifest.json

@@ -8,7 +8,7 @@
 		"64": "extension/ui/resources/icon_64.png",
 		"64": "extension/ui/resources/icon_64.png",
 		"128": "extension/ui/resources/icon_128.png"
 		"128": "extension/ui/resources/icon_128.png"
 	},
 	},
-	"version": "1.13.32",
+	"version": "1.14.0",
 	"description": "__MSG_extensionDescription__",
 	"description": "__MSG_extensionDescription__",
 	"content_scripts": [
 	"content_scripts": [
 		{
 		{
@@ -83,6 +83,7 @@
 			"extension/lib/single-file/fetch/bg/fetch.js",
 			"extension/lib/single-file/fetch/bg/fetch.js",
 			"extension/lib/single-file/frame-tree/bg/frame-tree.js",
 			"extension/lib/single-file/frame-tree/bg/frame-tree.js",
 			"extension/lib/single-file/lazy/bg/lazy-timeout.js",
 			"extension/lib/single-file/lazy/bg/lazy-timeout.js",
+			"extension/lib/woleet/woleet.js",
 			"extension/lib/gdrive/gdrive.js",
 			"extension/lib/gdrive/gdrive.js",
 			"extension/core/bg/config.js",
 			"extension/core/bg/config.js",
 			"extension/core/bg/tabs-data.js",
 			"extension/core/bg/tabs-data.js",