Merge branch 'master' into crowdin-translation

This commit is contained in:
El RIDO 2024-02-08 05:29:53 +01:00
commit 4db0db320b
10 changed files with 111 additions and 54 deletions

View File

@ -3,8 +3,13 @@
## 1.6.3 (not yet released) ## 1.6.3 (not yet released)
* ADDED: Translations for Romanian * ADDED: Translations for Romanian
* ADDED: Detect and report on damaged pastes (#1218) * ADDED: Detect and report on damaged pastes (#1218)
* CHANGED: Upgrading libraries to: zlib 1.3 * CHANGED: Ask for confirmation, before loading burn after reading pastes #1237
* CHANGED: Focus on password input in modal dialog
* CHANGED: Upgrading libraries to: DOMpurify 3.0.8 & zlib 1.3.1
* FIXED: Support more types of valid URLs for shorteners, incl. IDN ones (#1224) * FIXED: Support more types of valid URLs for shorteners, incl. IDN ones (#1224)
* FIXED: Email timezone buttons overlapping in some languages #1039
* FIXED: Changing language mangles URL #1191
* FIXED: Needless reload when visiting default URL
## 1.6.2 (2023-12-15) ## 1.6.2 (2023-12-15)
* FIXED: English not selectable when `languageselection` enabled (#1208) * FIXED: English not selectable when `languageselection` enabled (#1208)

View File

@ -214,5 +214,7 @@
"Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.", "Your IP is not authorized to create pastes.": "Your IP is not authorized to create pastes.",
"Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.", "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
"Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".", "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".": "Error calling YOURLS. Probably a configuration issue, like wrong or missing \"apiurl\" or \"signature\".",
"Error parsing YOURLS response.": "Error parsing YOURLS response." "Error parsing YOURLS response.": "Error parsing YOURLS response.",
"Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?": "Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?",
"Yes, load it": "Yes, load it"
} }

View File

@ -12,12 +12,12 @@ global.WebCrypto = require('@peculiar/webcrypto').Crypto;
// application libraries to test // application libraries to test
global.$ = global.jQuery = require('./jquery-3.7.0'); global.$ = global.jQuery = require('./jquery-3.7.0');
global.RawDeflate = require('./rawinflate-0.3').RawDeflate; global.RawDeflate = require('./rawinflate-0.3').RawDeflate;
global.zlib = require('./zlib-1.3').zlib; global.zlib = require('./zlib-1.3.1').zlib;
require('./prettify'); require('./prettify');
global.prettyPrint = window.PR.prettyPrint; global.prettyPrint = window.PR.prettyPrint;
global.prettyPrintOne = window.PR.prettyPrintOne; global.prettyPrintOne = window.PR.prettyPrintOne;
global.showdown = require('./showdown-2.1.0'); global.showdown = require('./showdown-2.1.0');
global.DOMPurify = require('./purify-3.0.6'); global.DOMPurify = require('./purify-3.0.8');
global.baseX = require('./base-x-4.0.0').baseX; global.baseX = require('./base-x-4.0.0').baseX;
global.Legacy = require('./legacy').Legacy; global.Legacy = require('./legacy').Legacy;
require('./bootstrap-3.4.1'); require('./bootstrap-3.4.1');

View File

@ -77,6 +77,13 @@ jQuery.PrivateBin = (function($, RawDeflate) {
} }
}; };
/**
* URL fragment prefix requiring load confirmation
*
* @private
*/
const loadConfirmPrefix = '#-';
/** /**
* CryptoData class * CryptoData class
* *
@ -228,7 +235,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
'<': '&lt;', '<': '&lt;',
'>': '&gt;', '>': '&gt;',
'"': '&quot;', '"': '&quot;',
"'": '&#39;', '\'': '&#39;',
'/': '&#x2F;', '/': '&#x2F;',
'`': '&#x60;', '`': '&#x60;',
'=': '&#x3D;' '=': '&#x3D;'
@ -1514,10 +1521,11 @@ jQuery.PrivateBin = (function($, RawDeflate) {
me.getPasteKey = function() me.getPasteKey = function()
{ {
if (symmetricKey === null) { if (symmetricKey === null) {
let newKey = window.location.hash.substring(1); let startPos = 1;
if (newKey === '') { if(window.location.hash.startsWith(loadConfirmPrefix)) {
throw 'no encryption key given'; startPos = loadConfirmPrefix.length;
} }
let newKey = window.location.hash.substring(startPos);
// Some web 2.0 services and redirectors add data AFTER the anchor // Some web 2.0 services and redirectors add data AFTER the anchor
// (such as &utm_source=...). We will strip any additional data. // (such as &utm_source=...). We will strip any additional data.
@ -1526,6 +1534,9 @@ jQuery.PrivateBin = (function($, RawDeflate) {
{ {
newKey = newKey.substring(0, ampersandPos); newKey = newKey.substring(0, ampersandPos);
} }
if (newKey === '') {
throw 'no encryption key given';
}
// version 2 uses base58, version 1 uses base64 without decoding // version 2 uses base58, version 1 uses base64 without decoding
try { try {
@ -2252,6 +2263,34 @@ jQuery.PrivateBin = (function($, RawDeflate) {
PasteDecrypter.run(); PasteDecrypter.run();
} }
/**
* Request users confirmation to load possibly burn after reading paste
*
* @name Prompt.requestLoadConfirmation
* @function
*/
me.requestLoadConfirmation = function()
{
const $loadconfirmmodal = $('#loadconfirmmodal');
if ($loadconfirmmodal.length > 0) {
const $loadconfirmOpenNow = $loadconfirmmodal.find('#loadconfirm-open-now');
$loadconfirmOpenNow.off('click.loadPaste');
$loadconfirmOpenNow.on('click.loadPaste', PasteDecrypter.run);
const $loadconfirmClose = $loadconfirmmodal.find('.close');
$loadconfirmClose.off('click.close');
$loadconfirmClose.on('click.close', Controller.newPaste);
$loadconfirmmodal.modal('show');
} else {
if (window.confirm(
I18n._('Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?')
)) {
PasteDecrypter.run();
} else {
Controller.newPaste();
}
}
}
/** /**
* ask the user for the password and set it * ask the user for the password and set it
* *
@ -2266,6 +2305,12 @@ jQuery.PrivateBin = (function($, RawDeflate) {
backdrop: 'static', backdrop: 'static',
keyboard: false keyboard: false
}); });
// focus password input
$passwordDecrypt.focus();
// then re-focus it, when modal causes it to loose focus again
setTimeout(function () {
$passwordDecrypt.focus();
}, 500);
return; return;
} }
@ -2325,13 +2370,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
$passwordForm = $('#passwordform'); $passwordForm = $('#passwordform');
$passwordModal = $('#passwordmodal'); $passwordModal = $('#passwordmodal');
// bind events // bind events - handle Model password submission
// focus password input when it is shown
$passwordModal.on('shown.bs.Model', function () {
$passwordDecrypt.focus();
});
// handle Model password submission
$passwordForm.submit(submitPasswordModal); $passwordForm.submit(submitPasswordModal);
}; };
@ -3565,7 +3604,6 @@ jQuery.PrivateBin = (function($, RawDeflate) {
if (fadeOut === true) { if (fadeOut === true) {
setTimeout(function () { setTimeout(function () {
$comment.removeClass('highlight'); $comment.removeClass('highlight');
}, 300); }, 300);
} }
}; };
@ -3813,6 +3851,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
{ {
document.cookie = 'lang=' + $(event.target).data('lang') + ';secure'; document.cookie = 'lang=' + $(event.target).data('lang') + ';secure';
UiHelper.reloadHome(); UiHelper.reloadHome();
event.preventDefault();
} }
/** /**
@ -3968,10 +4007,6 @@ jQuery.PrivateBin = (function($, RawDeflate) {
const $emailconfirmmodal = $('#emailconfirmmodal'); const $emailconfirmmodal = $('#emailconfirmmodal');
if ($emailconfirmmodal.length > 0) { if ($emailconfirmmodal.length > 0) {
if (expirationDate !== null) { if (expirationDate !== null) {
I18n._(
$emailconfirmmodal.find('#emailconfirm-display'),
'Recipient may become aware of your timezone, convert time to UTC?'
);
const $emailconfirmTimezoneCurrent = $emailconfirmmodal.find('#emailconfirm-timezone-current'); const $emailconfirmTimezoneCurrent = $emailconfirmmodal.find('#emailconfirm-timezone-current');
const $emailconfirmTimezoneUtc = $emailconfirmmodal.find('#emailconfirm-timezone-utc'); const $emailconfirmTimezoneUtc = $emailconfirmmodal.find('#emailconfirm-timezone-utc');
$emailconfirmTimezoneCurrent.off('click.sendEmailCurrentTimezone'); $emailconfirmTimezoneCurrent.off('click.sendEmailCurrentTimezone');
@ -4826,7 +4861,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
// show notification // show notification
const baseUri = Helper.baseUri() + '?', const baseUri = Helper.baseUri() + '?',
url = baseUri + data.id + '#' + CryptTool.base58encode(data.encryptionKey), url = baseUri + data.id + (TopNav.getBurnAfterReading() ? loadConfirmPrefix : '#') + CryptTool.base58encode(data.encryptionKey),
deleteUrl = baseUri + 'pasteid=' + data.id + '&deletetoken=' + data.deletetoken; deleteUrl = baseUri + 'pasteid=' + data.id + '&deletetoken=' + data.deletetoken;
PasteStatus.createPasteNotification(url, deleteUrl); PasteStatus.createPasteNotification(url, deleteUrl);
@ -5245,7 +5280,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
Alert.hideMessages(); Alert.hideMessages();
Alert.showLoading('Decrypting paste…', 'cloud-download'); Alert.showLoading('Decrypting paste…', 'cloud-download');
if (typeof paste === 'undefined') { if (typeof paste === 'undefined' || paste.type === 'click') {
// get cipher data and wait until it is available // get cipher data and wait until it is available
Model.getPasteData(me.run); Model.getPasteData(me.run);
return; return;
@ -5352,7 +5387,10 @@ jQuery.PrivateBin = (function($, RawDeflate) {
AttachmentViewer.removeAttachmentData(); AttachmentViewer.removeAttachmentData();
Alert.hideLoading(); Alert.hideLoading();
// only push new state if we are coming from a different one
if (Helper.baseUri() != window.location) {
history.pushState({type: 'create'}, document.title, Helper.baseUri()); history.pushState({type: 'create'}, document.title, Helper.baseUri());
}
// clear discussion // clear discussion
DiscussionViewer.prepareNewDiscussion(); DiscussionViewer.prepareNewDiscussion();
@ -5378,6 +5416,12 @@ jQuery.PrivateBin = (function($, RawDeflate) {
} }
} }
// check if we should request loading confirmation
if(window.location.hash.startsWith(loadConfirmPrefix)) {
Prompt.requestLoadConfirmation();
return;
}
// show proper elements on screen // show proper elements on screen
PasteDecrypter.run(); PasteDecrypter.run();
}; };

File diff suppressed because one or more lines are too long

2
js/purify-3.0.8.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -55,7 +55,7 @@ if ($ZEROBINCOMPATIBILITY) :
<?php <?php
endif; endif;
?> ?>
<script type="text/javascript" data-cfasync="false" src="js/zlib-1.3.js" integrity="sha512-VL3lLnt8EexTr22ze4a4HfVghpgY48c/Lhf4CcQa8bgYaIRRPjV1nP7EA8RiciGoXXQ1IeiU7tjrclPeVEfxOQ==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/zlib-1.3.1.js" integrity="sha512-VL3lLnt8EexTr22ze4a4HfVghpgY48c/Lhf4CcQa8bgYaIRRPjV1nP7EA8RiciGoXXQ1IeiU7tjrclPeVEfxOQ==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/base-x-4.0.0.js" integrity="sha512-nNPg5IGCwwrveZ8cA/yMGr5HiRS5Ps2H+s0J/mKTPjCPWUgFGGw7M5nqdnPD3VsRwCVysUh3Y8OWjeSKGkEQJQ==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/base-x-4.0.0.js" integrity="sha512-nNPg5IGCwwrveZ8cA/yMGr5HiRS5Ps2H+s0J/mKTPjCPWUgFGGw7M5nqdnPD3VsRwCVysUh3Y8OWjeSKGkEQJQ==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/bootstrap-3.4.1.js" integrity="sha512-oBTprMeNEKCnqfuqKd6sbvFzmFQtlXS3e0C/RGFV0hD6QzhHV+ODfaQbAlmY6/q0ubbwlAM/nCJjkrgA3waLzg==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/bootstrap-3.4.1.js" integrity="sha512-oBTprMeNEKCnqfuqKd6sbvFzmFQtlXS3e0C/RGFV0hD6QzhHV+ODfaQbAlmY6/q0ubbwlAM/nCJjkrgA3waLzg==" crossorigin="anonymous"></script>
@ -71,9 +71,9 @@ if ($MARKDOWN) :
<?php <?php
endif; endif;
?> ?>
<script type="text/javascript" data-cfasync="false" src="js/purify-3.0.6.js" integrity="sha512-N3y6/HOk3pbsw3lFh4O8CKKEVwu1B2CF8kinhjURf8Yqa5OfSUt+/arozxFW+TUPOPw3TsDCRT/0u7BGRTEVUw==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/purify-3.0.8.js" integrity="sha512-wWBDKh5wYGtJ1Df+PPZIn59jHVBnJ4/Yb2W/pVnzaXab8cmlZnHVx+FEBGu5JX39s3P2Qlt+aNQou0XnjW86hg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-cfRk8a/8RpvMb4g9Su9kcKNcs7+PyGioUxH6z6k9e4vcdZmtz+gM2HwIP/Gd/1r6h3qoxrkO4jodn2E7gtZ7EA==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-FPqSHNhZoXQX1vV5+Sd9vn/indcihNkt0KLmpRpDfXRMM9tTWxokUpbsD07GGpYibfG4mPbCwFy13c2VLvagIg==" crossorigin="anonymous"></script>
<!-- icon --> <!-- icon -->
<link rel="apple-touch-icon" href="<?php echo I18n::encode($BASEPATH); ?>img/apple-touch-icon.png" sizes="180x180" /> <link rel="apple-touch-icon" href="<?php echo I18n::encode($BASEPATH); ?>img/apple-touch-icon.png" sizes="180x180" />
<link rel="icon" type="image/png" href="img/favicon-32x32.png" sizes="32x32" /> <link rel="icon" type="image/png" href="img/favicon-32x32.png" sizes="32x32" />
@ -123,22 +123,32 @@ if (count($class)) {
</div> </div>
</div> </div>
</div> </div>
<div id="loadconfirmmodal" tabindex="-1" class="modal fade" role="dialog" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="<?php echo I18n::_('Close') ?>"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title"><?php echo I18n::_('Burn after reading pastes can only be displayed once upon loading it. Do you want to open it now?') ?></h4>
</div>
<div class="modal-body text-center">
<button id="loadconfirm-open-now" type="button" class="btn btn-success" data-dismiss="modal"><span class="glyphicon glyphicon-download"></span> <?php echo I18n::_('Yes, load it') ?></button>
</div>
</div>
</div>
</div>
<?php <?php
if ($QRCODE) : if ($QRCODE) :
?> ?>
<div id="qrcodemodal" tabindex="-1" class="modal fade" aria-labelledby="qrcodemodalTitle" role="dialog" aria-hidden="true"> <div id="qrcodemodal" tabindex="-1" class="modal fade" role="dialog" aria-hidden="true">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="<?php echo I18n::_('Close') ?>"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title"><?php echo I18n::_('QR code') ?></h4>
</div>
<div class="modal-body"> <div class="modal-body">
<div class="mx-auto" id="qrcode-display"></div> <div class="mx-auto" id="qrcode-display"></div>
</div> </div>
<div class="row">
<div class="btn-group col-xs-12">
<span class="col-xs-12">
<button type="button" class="btn btn-primary btn-block" data-dismiss="modal"><?php echo I18n::_('Close') ?></button>
</span>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -146,23 +156,19 @@ if ($QRCODE) :
endif; endif;
if ($EMAIL) : if ($EMAIL) :
?> ?>
<div id="emailconfirmmodal" tabindex="-1" class="modal fade" aria-labelledby="emailconfirmmodalTitle" role="dialog" aria-hidden="true"> <div id="emailconfirmmodal" tabindex="-1" class="modal fade" role="dialog" aria-hidden="true">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-body"> <div class="modal-header">
<div id="emailconfirm-display"></div> <button type="button" class="close" data-dismiss="modal" aria-label="<?php echo I18n::_('Close') ?>"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title"><?php echo I18n::_('Recipient may become aware of your timezone, convert time to UTC?') ?></h4>
</div> </div>
<div class="row"> <div class="modal-body row">
<div class="btn-group col-xs-12" data-toggle="buttons"> <div class="col-xs-12 col-md-6">
<span class="col-xs-12 col-md-4"> <button id="emailconfirm-timezone-current" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-time"></span> <?php echo I18n::_('Use Current Timezone') ?></button>
<button id="emailconfirm-timezone-current" type="button" class="btn btn-danger btn-block" data-dismiss="modal"><?php echo I18n::_('Use Current Timezone') ?></button> </div>
</span> <div class="col-xs-12 col-md-6 text-right">
<span class="col-xs-12 col-md-4"> <button id="emailconfirm-timezone-utc" type="button" class="btn btn-success"><span class="glyphicon glyphicon-globe"></span> <?php echo I18n::_('Convert To UTC') ?></button>
<button id="emailconfirm-timezone-utc" type="button" class="btn btn-default btn-block" data-dismiss="modal"><?php echo I18n::_('Convert To UTC') ?></button>
</span>
<span class="col-xs-12 col-md-4">
<button type="button" class="btn btn-primary btn-block" data-dismiss="modal"><?php echo I18n::_('Close') ?></button>
</span>
</div> </div>
</div> </div>
</div> </div>

View File

@ -34,7 +34,7 @@ if ($ZEROBINCOMPATIBILITY):
<?php <?php
endif; endif;
?> ?>
<script type="text/javascript" data-cfasync="false" src="js/zlib-1.3.js" integrity="sha512-VL3lLnt8EexTr22ze4a4HfVghpgY48c/Lhf4CcQa8bgYaIRRPjV1nP7EA8RiciGoXXQ1IeiU7tjrclPeVEfxOQ==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/zlib-1.3.1.js" integrity="sha512-VL3lLnt8EexTr22ze4a4HfVghpgY48c/Lhf4CcQa8bgYaIRRPjV1nP7EA8RiciGoXXQ1IeiU7tjrclPeVEfxOQ==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/base-x-4.0.0.js" integrity="sha512-nNPg5IGCwwrveZ8cA/yMGr5HiRS5Ps2H+s0J/mKTPjCPWUgFGGw7M5nqdnPD3VsRwCVysUh3Y8OWjeSKGkEQJQ==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/base-x-4.0.0.js" integrity="sha512-nNPg5IGCwwrveZ8cA/yMGr5HiRS5Ps2H+s0J/mKTPjCPWUgFGGw7M5nqdnPD3VsRwCVysUh3Y8OWjeSKGkEQJQ==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script>
<?php <?php
@ -49,9 +49,9 @@ if ($MARKDOWN):
<?php <?php
endif; endif;
?> ?>
<script type="text/javascript" data-cfasync="false" src="js/purify-3.0.6.js" integrity="sha512-N3y6/HOk3pbsw3lFh4O8CKKEVwu1B2CF8kinhjURf8Yqa5OfSUt+/arozxFW+TUPOPw3TsDCRT/0u7BGRTEVUw==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/purify-3.0.8.js" integrity="sha512-wWBDKh5wYGtJ1Df+PPZIn59jHVBnJ4/Yb2W/pVnzaXab8cmlZnHVx+FEBGu5JX39s3P2Qlt+aNQou0XnjW86hg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-cfRk8a/8RpvMb4g9Su9kcKNcs7+PyGioUxH6z6k9e4vcdZmtz+gM2HwIP/Gd/1r6h3qoxrkO4jodn2E7gtZ7EA==" crossorigin="anonymous"></script> <script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-FPqSHNhZoXQX1vV5+Sd9vn/indcihNkt0KLmpRpDfXRMM9tTWxokUpbsD07GGpYibfG4mPbCwFy13c2VLvagIg==" crossorigin="anonymous"></script>
<!-- icon --> <!-- icon -->
<link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" /> <link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
<link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" /> <link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />