diff --git a/CHANGELOG.md b/CHANGELOG.md
index b3278931..8e416b9e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,7 @@
* **1.4 (not yet released)**
* ADDED: Translation for Estonian
* ADDED: new HTTP headers improving security (#765)
+ * ADDED: Download button for paste text (#774)
* ADDED: Opt-out of federated learning of cohorts (FLoC) (#776)
* CHANGED: Language selection cookie only transmitted over HTTPS (#472)
* **1.3.5 (2021-04-05)**
diff --git a/cfg/conf.sample.php b/cfg/conf.sample.php
index 570503ce..ceddad62 100644
--- a/cfg/conf.sample.php
+++ b/cfg/conf.sample.php
@@ -87,7 +87,7 @@ languageselection = false
; async functions and display an error if not and for Chrome to enable
; webassembly support (used for zlib compression). You can remove it if Chrome
; doesn't need to be supported and old browsers don't need to be warned.
-; cspheader = "default-src 'none'; base-uri 'self'; manifest-src 'self'; connect-src * blob:; script-src 'self' 'unsafe-eval' resource:; style-src 'self'; font-src 'self'; img-src 'self' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads"
+; cspheader = "default-src 'none'; base-uri 'self'; form-action 'none'; manifest-src 'self'; connect-src * blob:; script-src 'self' 'unsafe-eval' resource:; style-src 'self'; font-src 'self'; img-src 'self' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads"
; stay compatible with PrivateBin Alpha 0.19, less secure
; if enabled will use base64.js version 1.7 instead of 2.1.9 and sha1 instead of
diff --git a/css/privatebin.css b/css/privatebin.css
index 8b4e6a0a..f852d396 100644
--- a/css/privatebin.css
+++ b/css/privatebin.css
@@ -249,6 +249,10 @@ button img {
padding: 1px 0 1px 0;
}
+#downloadtextbutton img {
+ padding: 1px 0 1px 0;
+}
+
#remainingtime, #password {
color: #94a3b4;
display: inline;
diff --git a/i18n/en.json b/i18n/en.json
index 295f5129..a96bab5d 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -184,5 +184,6 @@
"Close": "Close",
"Encrypted note on PrivateBin": "Encrypted note on PrivateBin",
"Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
- "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL."
+ "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
+ "Save paste": "Save paste"
}
diff --git a/js/privatebin.js b/js/privatebin.js
index 05199701..6218700a 100644
--- a/js/privatebin.js
+++ b/js/privatebin.js
@@ -3525,6 +3525,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
$password,
$passwordInput,
$rawTextButton,
+ $downloadTextButton,
$qrCodeLink,
$emailLink,
$sendButton,
@@ -3666,6 +3667,30 @@ jQuery.PrivateBin = (function($, RawDeflate) {
newDoc.close();
}
+ /**
+ * download text
+ *
+ * @name TopNav.downloadText
+ * @private
+ * @function
+ */
+ function downloadText()
+ {
+ var filename='paste-' + Model.getPasteId() + '.txt';
+ var text = PasteViewer.getText();
+
+ var element = document.createElement('a');
+ element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
+ element.setAttribute('download', filename);
+
+ element.style.display = 'none';
+ document.body.appendChild(element);
+
+ element.click();
+
+ document.body.removeChild(element);
+ }
+
/**
* saves the language in a cookie and reloads the page
*
@@ -3892,6 +3917,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
$newButton.removeClass('hidden');
$cloneButton.removeClass('hidden');
$rawTextButton.removeClass('hidden');
+ $downloadTextButton.removeClass('hidden');
$qrCodeLink.removeClass('hidden');
viewButtonsDisplayed = true;
@@ -3912,6 +3938,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
$cloneButton.addClass('hidden');
$newButton.addClass('hidden');
$rawTextButton.addClass('hidden');
+ $downloadTextButton.addClass('hidden');
$qrCodeLink.addClass('hidden');
me.hideEmailButton();
@@ -4073,6 +4100,17 @@ jQuery.PrivateBin = (function($, RawDeflate) {
$rawTextButton.addClass('hidden');
};
+ /**
+ * only hides the download text button
+ *
+ * @name TopNav.hideRawButton
+ * @function
+ */
+ me.hideDownloadButton = function()
+ {
+ $downloadTextButton.addClass('hidden');
+ };
+
/**
* only hides the qr code button
*
@@ -4334,6 +4372,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
$password = $('#password');
$passwordInput = $('#passwordinput');
$rawTextButton = $('#rawtextbutton');
+ $downloadTextButton = $('#downloadtextbutton');
$retryButton = $('#retrybutton');
$sendButton = $('#sendbutton');
$qrCodeLink = $('#qrcodelink');
@@ -4351,6 +4390,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
$sendButton.click(PasteEncrypter.sendPaste);
$cloneButton.click(Controller.clonePaste);
$rawTextButton.click(rawText);
+ $downloadTextButton.click(downloadText);
$retryButton.click(clickRetryButton);
$fileRemoveButton.click(removeAttachment);
$qrCodeLink.click(displayQrCode);
@@ -4689,6 +4729,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
TopNav.showEmailButton();
TopNav.hideRawButton();
+ TopNav.hideDownloadButton();
Editor.hide();
// parse and show text
diff --git a/lib/Configuration.php b/lib/Configuration.php
index 426cd158..e509d983 100644
--- a/lib/Configuration.php
+++ b/lib/Configuration.php
@@ -55,7 +55,7 @@ class Configuration
'urlshortener' => '',
'qrcode' => true,
'icon' => 'identicon',
- 'cspheader' => 'default-src \'none\'; base-uri \'self\'; manifest-src \'self\'; connect-src * blob:; script-src \'self\' \'unsafe-eval\' resource:; style-src \'self\'; font-src \'self\'; img-src \'self\' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads',
+ 'cspheader' => 'default-src \'none\'; base-uri \'self\'; form-action \'none\'; manifest-src \'self\'; connect-src * blob:; script-src \'self\' \'unsafe-eval\' resource:; style-src \'self\'; font-src \'self\'; img-src \'self\' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads',
'zerobincompatibility' => false,
'httpwarning' => true,
'compression' => 'zlib',
diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php
index f8f94446..1e4eae00 100644
--- a/tpl/bootstrap.php
+++ b/tpl/bootstrap.php
@@ -72,7 +72,7 @@ endif;
?>
-
+
@@ -212,6 +212,9 @@ endif;
+
diff --git a/tpl/page.php b/tpl/page.php
index a2272326..28f37b90 100644
--- a/tpl/page.php
+++ b/tpl/page.php
@@ -50,7 +50,7 @@ endif;
?>
-
+
@@ -127,6 +127,7 @@ endif;
+