Merge branch 'hardening'
This commit is contained in:
commit
1dd53a93f4
11 changed files with 122 additions and 46 deletions
|
@ -9,11 +9,15 @@
|
||||||
* ADDED: Google Cloud Storage backend support (#795)
|
* ADDED: Google Cloud Storage backend support (#795)
|
||||||
* ADDED: Oracle database support (#868)
|
* ADDED: Oracle database support (#868)
|
||||||
* ADDED: Configuration option to limit paste creation and commenting to certain IPs (#883)
|
* ADDED: Configuration option to limit paste creation and commenting to certain IPs (#883)
|
||||||
|
* ADDED: Set CSP also as meta tag, to deal with misconfigured webservers mangling the HTTP header
|
||||||
|
* ADDED: Sanitize SVG preview, preventing script execution in instance context
|
||||||
* CHANGED: Language selection cookie only transmitted over HTTPS (#472)
|
* CHANGED: Language selection cookie only transmitted over HTTPS (#472)
|
||||||
* CHANGED: Upgrading libraries to: base-x 4.0.0, bootstrap 3.4.1 (JS), DOMpurify 2.3.6, ip-lib 1.18.0, jQuery 3.6.0, random_compat 2.0.21 & Showdown 2.0.0
|
* CHANGED: Upgrading libraries to: base-x 4.0.0, bootstrap 3.4.1 (JS), DOMpurify 2.3.6, ip-lib 1.18.0, jQuery 3.6.0, random_compat 2.0.21 & Showdown 2.0.3
|
||||||
* CHANGED: Removed automatic `.ini` configuration file migration (#808)
|
* CHANGED: Removed automatic `.ini` configuration file migration (#808)
|
||||||
* CHANGED: Removed configurable `dir` for `traffic` & `purge` limiters (#419)
|
* CHANGED: Removed configurable `dir` for `traffic` & `purge` limiters (#419)
|
||||||
* CHANGED: Server salt, traffic and purge limiter now stored in the storage backend (#419)
|
* CHANGED: Server salt, traffic and purge limiter now stored in the storage backend (#419)
|
||||||
|
* CHANGED: Drop support for attachment download in IE
|
||||||
|
* FIXED: Error when attachments are disabled, but paste with attachment gets displayed
|
||||||
* **1.3.5 (2021-04-05)**
|
* **1.3.5 (2021-04-05)**
|
||||||
* ADDED: Translations for Hebrew, Lithuanian, Indonesian and Catalan
|
* ADDED: Translations for Hebrew, Lithuanian, Indonesian and Catalan
|
||||||
* ADDED: Make the project info configurable (#681)
|
* ADDED: Make the project info configurable (#681)
|
||||||
|
|
|
@ -87,7 +87,7 @@ languageselection = false
|
||||||
; async functions and display an error if not and for Chrome to enable
|
; 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
|
; 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.
|
; doesn't need to be supported and old browsers don't need to be warned.
|
||||||
; 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'; frame-ancestors 'none'; 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'; style-src 'self'; font-src 'self'; frame-ancestors 'none'; 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
|
; 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
|
; if enabled will use base64.js version 1.7 instead of 2.1.9 and sha1 instead of
|
||||||
|
|
|
@ -16,7 +16,7 @@ global.zlib = require('./zlib-1.2.11').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.0.0');
|
global.showdown = require('./showdown-2.0.3');
|
||||||
global.DOMPurify = require('./purify-2.3.6');
|
global.DOMPurify = require('./purify-2.3.6');
|
||||||
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;
|
||||||
|
|
130
js/privatebin.js
130
js/privatebin.js
|
@ -52,6 +52,31 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||||
*/
|
*/
|
||||||
let z;
|
let z;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DOMpurify settings for HTML content
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
const purifyHtmlConfig = {
|
||||||
|
ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|mailto|magnet):)/i,
|
||||||
|
SAFE_FOR_JQUERY: true,
|
||||||
|
USE_PROFILES: {
|
||||||
|
html: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DOMpurify settings for SVG content
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
const purifySvgConfig = {
|
||||||
|
USE_PROFILES: {
|
||||||
|
svg: true,
|
||||||
|
svgFilters: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CryptoData class
|
* CryptoData class
|
||||||
*
|
*
|
||||||
|
@ -409,7 +434,8 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||||
element.html().replace(
|
element.html().replace(
|
||||||
/(((https?|ftp):\/\/[\w?!=&.\/-;#@~%+*-]+(?![\w\s?!&.\/;#~%"=-]>))|((magnet):[\w?=&.\/-;#@~%+*-]+))/ig,
|
/(((https?|ftp):\/\/[\w?!=&.\/-;#@~%+*-]+(?![\w\s?!&.\/;#~%"=-]>))|((magnet):[\w?=&.\/-;#@~%+*-]+))/ig,
|
||||||
'<a href="$1" rel="nofollow noopener noreferrer">$1</a>'
|
'<a href="$1" rel="nofollow noopener noreferrer">$1</a>'
|
||||||
)
|
),
|
||||||
|
purifyHtmlConfig
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -2536,7 +2562,8 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||||
// let showdown convert the HTML and sanitize HTML *afterwards*!
|
// let showdown convert the HTML and sanitize HTML *afterwards*!
|
||||||
$plainText.html(
|
$plainText.html(
|
||||||
DOMPurify.sanitize(
|
DOMPurify.sanitize(
|
||||||
converter.makeHtml(text)
|
converter.makeHtml(text),
|
||||||
|
purifyHtmlConfig
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
// add table classes from bootstrap css
|
// add table classes from bootstrap css
|
||||||
|
@ -2752,6 +2779,34 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||||
$dropzone;
|
$dropzone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* get blob URL from string data and mime type
|
||||||
|
*
|
||||||
|
* @name AttachmentViewer.getBlobUrl
|
||||||
|
* @private
|
||||||
|
* @function
|
||||||
|
* @param {string} data - raw data of attachment
|
||||||
|
* @param {string} data - mime type of attachment
|
||||||
|
* @return {string} objectURL
|
||||||
|
*/
|
||||||
|
function getBlobUrl(data, mimeType)
|
||||||
|
{
|
||||||
|
// Transform into a Blob
|
||||||
|
const buf = new Uint8Array(data.length);
|
||||||
|
for (let i = 0; i < data.length; ++i) {
|
||||||
|
buf[i] = data.charCodeAt(i);
|
||||||
|
}
|
||||||
|
const blob = new window.Blob(
|
||||||
|
[buf],
|
||||||
|
{
|
||||||
|
type: mimeType
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Get blob URL
|
||||||
|
return window.URL.createObjectURL(blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* sets the attachment but does not yet show it
|
* sets the attachment but does not yet show it
|
||||||
*
|
*
|
||||||
* @name AttachmentViewer.setAttachment
|
* @name AttachmentViewer.setAttachment
|
||||||
|
@ -2761,44 +2816,42 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||||
*/
|
*/
|
||||||
me.setAttachment = function(attachmentData, fileName)
|
me.setAttachment = function(attachmentData, fileName)
|
||||||
{
|
{
|
||||||
// data URI format: data:[<mediaType>][;base64],<data>
|
// skip, if attachments got disabled
|
||||||
|
if (!$attachmentLink || !$attachmentPreview) return;
|
||||||
|
|
||||||
|
// data URI format: data:[<mimeType>][;base64],<data>
|
||||||
|
|
||||||
// position in data URI string of where data begins
|
// position in data URI string of where data begins
|
||||||
const base64Start = attachmentData.indexOf(',') + 1;
|
const base64Start = attachmentData.indexOf(',') + 1;
|
||||||
// position in data URI string of where mediaType ends
|
// position in data URI string of where mimeType ends
|
||||||
const mediaTypeEnd = attachmentData.indexOf(';');
|
const mimeTypeEnd = attachmentData.indexOf(';');
|
||||||
|
|
||||||
// extract mediaType
|
// extract mimeType
|
||||||
const mediaType = attachmentData.substring(5, mediaTypeEnd);
|
const mimeType = attachmentData.substring(5, mimeTypeEnd);
|
||||||
// extract data and convert to binary
|
// extract data and convert to binary
|
||||||
const rawData = attachmentData.substring(base64Start);
|
const rawData = attachmentData.substring(base64Start);
|
||||||
const decodedData = rawData.length > 0 ? atob(rawData) : '';
|
const decodedData = rawData.length > 0 ? atob(rawData) : '';
|
||||||
|
|
||||||
// Transform into a Blob
|
let blobUrl = getBlobUrl(decodedData, mimeType);
|
||||||
const buf = new Uint8Array(decodedData.length);
|
$attachmentLink.attr('href', blobUrl);
|
||||||
for (let i = 0; i < decodedData.length; ++i) {
|
|
||||||
buf[i] = decodedData.charCodeAt(i);
|
|
||||||
}
|
|
||||||
const blob = new window.Blob([ buf ], { type: mediaType });
|
|
||||||
|
|
||||||
// Get Blob URL
|
|
||||||
const blobUrl = window.URL.createObjectURL(blob);
|
|
||||||
|
|
||||||
// IE does not support setting a data URI on an a element
|
|
||||||
// Using msSaveBlob to download
|
|
||||||
if (window.Blob && navigator.msSaveBlob) {
|
|
||||||
$attachmentLink.off('click').on('click', function () {
|
|
||||||
navigator.msSaveBlob(blob, fileName);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$attachmentLink.attr('href', blobUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof fileName !== 'undefined') {
|
if (typeof fileName !== 'undefined') {
|
||||||
$attachmentLink.attr('download', fileName);
|
$attachmentLink.attr('download', fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
me.handleBlobAttachmentPreview($attachmentPreview, blobUrl, mediaType);
|
// sanitize SVG preview
|
||||||
|
// prevents executing embedded scripts when CSP is not set and user
|
||||||
|
// right-clicks/long-taps and opens the SVG in a new tab - prevented
|
||||||
|
// in the preview by use of an img tag, which disables scripts, too
|
||||||
|
if (mimeType.match(/^image\/.*svg/i)) {
|
||||||
|
const sanitizedData = DOMPurify.sanitize(
|
||||||
|
decodedData,
|
||||||
|
purifySvgConfig
|
||||||
|
);
|
||||||
|
blobUrl = getBlobUrl(sanitizedData, mimeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
me.handleBlobAttachmentPreview($attachmentPreview, blobUrl, mimeType);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2809,6 +2862,9 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||||
*/
|
*/
|
||||||
me.showAttachment = function()
|
me.showAttachment = function()
|
||||||
{
|
{
|
||||||
|
// skip, if attachments got disabled
|
||||||
|
if (!$attachment || !$attachmentPreview) return;
|
||||||
|
|
||||||
$attachment.removeClass('hidden');
|
$attachment.removeClass('hidden');
|
||||||
|
|
||||||
if (attachmentHasPreview) {
|
if (attachmentHasPreview) {
|
||||||
|
@ -3016,13 +3072,13 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||||
me.handleBlobAttachmentPreview = function ($targetElement, blobUrl, mimeType) {
|
me.handleBlobAttachmentPreview = function ($targetElement, blobUrl, mimeType) {
|
||||||
if (blobUrl) {
|
if (blobUrl) {
|
||||||
attachmentHasPreview = true;
|
attachmentHasPreview = true;
|
||||||
if (mimeType.match(/image\//i)) {
|
if (mimeType.match(/^image\//i)) {
|
||||||
$targetElement.html(
|
$targetElement.html(
|
||||||
$(document.createElement('img'))
|
$(document.createElement('img'))
|
||||||
.attr('src', blobUrl)
|
.attr('src', blobUrl)
|
||||||
.attr('class', 'img-thumbnail')
|
.attr('class', 'img-thumbnail')
|
||||||
);
|
);
|
||||||
} else if (mimeType.match(/video\//i)) {
|
} else if (mimeType.match(/^video\//i)) {
|
||||||
$targetElement.html(
|
$targetElement.html(
|
||||||
$(document.createElement('video'))
|
$(document.createElement('video'))
|
||||||
.attr('controls', 'true')
|
.attr('controls', 'true')
|
||||||
|
@ -3033,7 +3089,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||||
.attr('type', mimeType)
|
.attr('type', mimeType)
|
||||||
.attr('src', blobUrl))
|
.attr('src', blobUrl))
|
||||||
);
|
);
|
||||||
} else if (mimeType.match(/audio\//i)) {
|
} else if (mimeType.match(/^audio\//i)) {
|
||||||
$targetElement.html(
|
$targetElement.html(
|
||||||
$(document.createElement('audio'))
|
$(document.createElement('audio'))
|
||||||
.attr('controls', 'true')
|
.attr('controls', 'true')
|
||||||
|
@ -3665,7 +3721,14 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||||
for (let i = 0; i < $head.length; ++i) {
|
for (let i = 0; i < $head.length; ++i) {
|
||||||
newDoc.write($head[i].outerHTML);
|
newDoc.write($head[i].outerHTML);
|
||||||
}
|
}
|
||||||
newDoc.write('</head><body><pre>' + DOMPurify.sanitize(Helper.htmlEntities(paste)) + '</pre></body></html>');
|
newDoc.write(
|
||||||
|
'</head><body><pre>' +
|
||||||
|
DOMPurify.sanitize(
|
||||||
|
Helper.htmlEntities(paste),
|
||||||
|
purifyHtmlConfig
|
||||||
|
) +
|
||||||
|
'</pre></body></html>'
|
||||||
|
);
|
||||||
newDoc.close();
|
newDoc.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5394,11 +5457,6 @@ jQuery.PrivateBin = (function($, RawDeflate) {
|
||||||
// first load translations
|
// first load translations
|
||||||
I18n.loadTranslations();
|
I18n.loadTranslations();
|
||||||
|
|
||||||
DOMPurify.setConfig({
|
|
||||||
ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|mailto|magnet):)/i,
|
|
||||||
SAFE_FOR_JQUERY: true
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add a hook to make all links open a new window
|
// Add a hook to make all links open a new window
|
||||||
DOMPurify.addHook('afterSanitizeAttributes', function(node) {
|
DOMPurify.addHook('afterSanitizeAttributes', function(node) {
|
||||||
// set all elements owning target to target=_blank
|
// set all elements owning target to target=_blank
|
||||||
|
|
File diff suppressed because one or more lines are too long
2
js/showdown-2.0.3.js
Normal file
2
js/showdown-2.0.3.js
Normal file
File diff suppressed because one or more lines are too long
|
@ -54,7 +54,7 @@ class Configuration
|
||||||
'urlshortener' => '',
|
'urlshortener' => '',
|
||||||
'qrcode' => true,
|
'qrcode' => true,
|
||||||
'icon' => 'identicon',
|
'icon' => 'identicon',
|
||||||
'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\'; frame-ancestors \'none\'; 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\'; style-src \'self\'; font-src \'self\'; frame-ancestors \'none\'; 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,
|
'zerobincompatibility' => false,
|
||||||
'httpwarning' => true,
|
'httpwarning' => true,
|
||||||
'compression' => 'zlib',
|
'compression' => 'zlib',
|
||||||
|
|
|
@ -364,6 +364,16 @@ class Controller
|
||||||
setcookie('lang', $languageselection, 0, '', '', true);
|
setcookie('lang', $languageselection, 0, '', '', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// strip policies that are unsupported in meta tag
|
||||||
|
$metacspheader = str_replace(
|
||||||
|
array(
|
||||||
|
'frame-ancestors \'none\'; ',
|
||||||
|
'; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals allow-downloads',
|
||||||
|
),
|
||||||
|
'',
|
||||||
|
$this->_conf->getKey('cspheader')
|
||||||
|
);
|
||||||
|
|
||||||
$page = new View;
|
$page = new View;
|
||||||
$page->assign('NAME', $this->_conf->getKey('name'));
|
$page->assign('NAME', $this->_conf->getKey('name'));
|
||||||
$page->assign('BASEPATH', I18n::_($this->_conf->getKey('basepath')));
|
$page->assign('BASEPATH', I18n::_($this->_conf->getKey('basepath')));
|
||||||
|
@ -392,6 +402,7 @@ class Controller
|
||||||
$page->assign('HTTPWARNING', $this->_conf->getKey('httpwarning'));
|
$page->assign('HTTPWARNING', $this->_conf->getKey('httpwarning'));
|
||||||
$page->assign('HTTPSLINK', 'https://' . $this->_request->getHost() . $this->_request->getRequestUri());
|
$page->assign('HTTPSLINK', 'https://' . $this->_request->getHost() . $this->_request->getRequestUri());
|
||||||
$page->assign('COMPRESSION', $this->_conf->getKey('compression'));
|
$page->assign('COMPRESSION', $this->_conf->getKey('compression'));
|
||||||
|
$page->assign('CSPHEADER', $metacspheader);
|
||||||
$page->draw($this->_conf->getKey('template'));
|
$page->draw($this->_conf->getKey('template'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ $isPage = substr($template, -5) === '-page';
|
||||||
<html lang="<?php echo I18n::_('en'); ?>">
|
<html lang="<?php echo I18n::_('en'); ?>">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
<meta http-equiv="Content-Security-Policy" content="<?php echo I18n::encode($CSPHEADER); ?>">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta name="robots" content="noindex" />
|
<meta name="robots" content="noindex" />
|
||||||
|
@ -66,13 +67,13 @@ if ($SYNTAXHIGHLIGHTING) :
|
||||||
endif;
|
endif;
|
||||||
if ($MARKDOWN) :
|
if ($MARKDOWN) :
|
||||||
?>
|
?>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/showdown-2.0.0.js" integrity="sha512-UB9jpMTOJLSnVzePuqlSGT34G70wEGqtIWabMeAh+Drnj4/uQ8rFkFn1zkN9vkWp/7nA51U2LmP23H5MJvBXsw==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/showdown-2.0.3.js" integrity="sha512-vcfjvW3UKHD/4vlQx804cqWK88jFmjsWRsZ8/u5YEcyHB1IituxrXDU7TvdqsFVsMnxpE/UIEo25/SYW+puWHw==" crossorigin="anonymous"></script>
|
||||||
<?php
|
<?php
|
||||||
endif;
|
endif;
|
||||||
?>
|
?>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/purify-2.3.6.js" integrity="sha512-N1GGPjbqLbwK821ZN7C925WuTwU4aDxz2CEEOXQ6/s6m6MBwVj8fh5fugiE2hzsm0xud3q7jpjZQ4ILnpMREYQ==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/purify-2.3.6.js" integrity="sha512-N1GGPjbqLbwK821ZN7C925WuTwU4aDxz2CEEOXQ6/s6m6MBwVj8fh5fugiE2hzsm0xud3q7jpjZQ4ILnpMREYQ==" 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-EdUms2nI12Cmtv014stIEBlyPjeKMHlkg7NiBJup1b7jJF5amKhev2RwTaldINXK4UaWbZtQ6hGuMPNvvNQZFA==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-kFUoM3Qg6VzRTJGau3wWP2IRZQF2WToL7Dgvazxqp0jgYIKA5cCK9xFy9Zes208XX0nYP64scW2nJIYNk9pL6Q==" 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" />
|
||||||
|
|
|
@ -4,6 +4,7 @@ use PrivateBin\I18n;
|
||||||
<html lang="<?php echo I18n::_('en'); ?>">
|
<html lang="<?php echo I18n::_('en'); ?>">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
|
<meta http-equiv="Content-Security-Policy" content="<?php echo I18n::encode($CSPHEADER); ?>">
|
||||||
<meta name="robots" content="noindex" />
|
<meta name="robots" content="noindex" />
|
||||||
<meta name="google" content="notranslate">
|
<meta name="google" content="notranslate">
|
||||||
<title><?php echo I18n::_($NAME); ?></title>
|
<title><?php echo I18n::_($NAME); ?></title>
|
||||||
|
@ -44,13 +45,13 @@ if ($SYNTAXHIGHLIGHTING):
|
||||||
endif;
|
endif;
|
||||||
if ($MARKDOWN):
|
if ($MARKDOWN):
|
||||||
?>
|
?>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/showdown-2.0.0.js" integrity="sha512-UB9jpMTOJLSnVzePuqlSGT34G70wEGqtIWabMeAh+Drnj4/uQ8rFkFn1zkN9vkWp/7nA51U2LmP23H5MJvBXsw==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/showdown-2.0.3.js" integrity="sha512-vcfjvW3UKHD/4vlQx804cqWK88jFmjsWRsZ8/u5YEcyHB1IituxrXDU7TvdqsFVsMnxpE/UIEo25/SYW+puWHw==" crossorigin="anonymous"></script>
|
||||||
<?php
|
<?php
|
||||||
endif;
|
endif;
|
||||||
?>
|
?>
|
||||||
<script type="text/javascript" data-cfasync="false" src="js/purify-2.3.6.js" integrity="sha512-N1GGPjbqLbwK821ZN7C925WuTwU4aDxz2CEEOXQ6/s6m6MBwVj8fh5fugiE2hzsm0xud3q7jpjZQ4ILnpMREYQ==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/purify-2.3.6.js" integrity="sha512-N1GGPjbqLbwK821ZN7C925WuTwU4aDxz2CEEOXQ6/s6m6MBwVj8fh5fugiE2hzsm0xud3q7jpjZQ4ILnpMREYQ==" 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-EdUms2nI12Cmtv014stIEBlyPjeKMHlkg7NiBJup1b7jJF5amKhev2RwTaldINXK4UaWbZtQ6hGuMPNvvNQZFA==" crossorigin="anonymous"></script>
|
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-kFUoM3Qg6VzRTJGau3wWP2IRZQF2WToL7Dgvazxqp0jgYIKA5cCK9xFy9Zes208XX0nYP64scW2nJIYNk9pL6Q==" 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" />
|
||||||
|
|
|
@ -60,6 +60,7 @@ class ViewTest extends PHPUnit_Framework_TestCase
|
||||||
$page->assign('HTTPWARNING', true);
|
$page->assign('HTTPWARNING', true);
|
||||||
$page->assign('HTTPSLINK', 'https://example.com/');
|
$page->assign('HTTPSLINK', 'https://example.com/');
|
||||||
$page->assign('COMPRESSION', 'zlib');
|
$page->assign('COMPRESSION', 'zlib');
|
||||||
|
$page->assign('CSPHEADER', 'default-src \'none\'');
|
||||||
|
|
||||||
$dir = dir(PATH . 'tpl');
|
$dir = dir(PATH . 'tpl');
|
||||||
while (false !== ($file = $dir->read())) {
|
while (false !== ($file = $dir->read())) {
|
||||||
|
|
Loading…
Reference in a new issue