diff --git a/cfg/conf.sample.php b/cfg/conf.sample.php index d2d285d..863974a 100644 --- a/cfg/conf.sample.php +++ b/cfg/conf.sample.php @@ -79,7 +79,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'; manifest-src 'self'; connect-src * blob:; script-src 'self' 'unsafe-eval'; 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" +; cspheader = "default-src '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" ; 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/js/privatebin.js b/js/privatebin.js index 23344dd..6826da4 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -243,6 +243,18 @@ jQuery.PrivateBin = (function($, RawDeflate) { */ const day = 86400; + /** + * number of seconds in a week + * + * = 60 * 60 * 24 * 7 seconds + * + * @name Helper.week + * @private + * @enum {number} + * @readonly + */ + const week = 604800; + /** * number of seconds in a month (30 days, an approximation) * @@ -326,7 +338,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { */ me.durationToSeconds = function(duration) { - let pieces = duration.split(/\d+/), + let pieces = duration.split(/(\D+)/), factor = pieces[0] || 0, timespan = pieces[1] || pieces[0]; switch (timespan) @@ -337,6 +349,8 @@ jQuery.PrivateBin = (function($, RawDeflate) { return factor * hour; case 'day': return factor * day; + case 'week': + return factor * week; case 'month': return factor * month; case 'year': @@ -391,9 +405,11 @@ jQuery.PrivateBin = (function($, RawDeflate) { me.urls2links = function(element) { element.html( - element.html().replace( - /(((https?|ftp):\/\/[\w?!=&.\/-;#@~%+*-]+(?![\w\s?!&.\/;#~%"=-]>))|((magnet):[\w?=&.\/-;#@~%+*-]+))/ig, - '$1' + DOMPurify.sanitize( + element.html().replace( + /(((https?|ftp):\/\/[\w?!=&.\/-;#@~%+*-]+(?![\w\s?!&.\/;#~%"=-]>))|((magnet):[\w?=&.\/-;#@~%+*-]+))/ig, + '$1' + ) ) ); }; @@ -1975,15 +1991,11 @@ jQuery.PrivateBin = (function($, RawDeflate) { return a.length - b.length; })[0]; if (typeof shortUrl === 'string' && shortUrl.length > 0) { - I18n._( - $('#pastelink'), - 'Your paste is %s (Hit [Ctrl]+[c] to copy)', - shortUrl, shortUrl - ); // we disable the button to avoid calling shortener again $shortenButton.addClass('buttondisabled'); - // save newly created element - $pasteUrl = $('#pasteurl'); + // update link + $pasteUrl.text(shortUrl); + $pasteUrl.prop('href', shortUrl); // we pre-select the link so that the user only has to [Ctrl]+[c] the link Helper.selectText($pasteUrl[0]); return; @@ -2404,7 +2416,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { /** * hides the Editor * - * @name Editor.reset + * @name Editor.hide * @function */ me.hide = function() @@ -3110,19 +3122,15 @@ jQuery.PrivateBin = (function($, RawDeflate) { */ function addClipboardEventHandler() { $(document).on('paste', function (event) { - if (TopNav.isAttachmentReadonly()) { - event.stopPropagation(); - event.preventDefault(); - return false; - } const items = (event.clipboardData || event.originalEvent.clipboardData).items; - for (let i = 0; i < items.length; ++i) { - if (items[i].kind === 'file') { - //Clear the file input: - $fileInput.wrap('
').closest('form').get(0).reset(); - $fileInput.unwrap(); - - readFileData(items[i].getAsFile()); + const lastItem = items[items.length - 1]; + if (lastItem.kind === 'file') { + if (TopNav.isAttachmentReadonly()) { + event.stopPropagation(); + event.preventDefault(); + return false; + } else { + readFileData(lastItem.getAsFile()); } } }); @@ -3752,8 +3760,12 @@ jQuery.PrivateBin = (function($, RawDeflate) { if (expirationDateString !== null) { emailBody += EOL; emailBody += BULLET; - emailBody += I18n._( - 'This link will expire after %s.', + // avoid DOMPurify mess with forward slash in expirationDateString + emailBody += Helper.sprintf( + I18n._( + 'This link will expire after %s.', + '%s' + ), expirationDateString ); } @@ -4280,7 +4292,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { */ me.isAttachmentReadonly = function() { - return createButtonsDisplayed && $attach.hasClass('hidden'); + return !createButtonsDisplayed || $attach.hasClass('hidden'); } /** @@ -5328,6 +5340,23 @@ jQuery.PrivateBin = (function($, RawDeflate) { SAFE_FOR_JQUERY: true }); + // Add a hook to make all links open a new window + DOMPurify.addHook('afterSanitizeAttributes', function(node) { + // set all elements owning target to target=_blank + if ('target' in node && node.id !== 'pasteurl') { + node.setAttribute('target', '_blank'); + } + // set non-HTML/MathML links to xlink:show=new + if (!node.hasAttribute('target') + && (node.hasAttribute('xlink:href') + || node.hasAttribute('href'))) { + node.setAttribute('xlink:show', 'new'); + } + if ('rel' in node) { + node.setAttribute('rel', 'nofollow noopener noreferrer'); + } + }); + // center all modals $('.modal').on('show.bs.modal', function(e) { $(e.target).css({ @@ -5359,6 +5388,12 @@ jQuery.PrivateBin = (function($, RawDeflate) { } me.initZ(); + // if delete token is passed (i.e. paste has been deleted by this + // access), there is nothing more to do + if (Model.hasDeleteToken()) { + return; + } + // check whether existing paste needs to be shown try { Model.getPasteId(); @@ -5367,11 +5402,10 @@ jQuery.PrivateBin = (function($, RawDeflate) { return me.newPaste(); } - // if delete token is passed (i.e. paste has been deleted by this - // access), there is nothing more to do - if (Model.hasDeleteToken()) { - return; - } + // always reload on back button to invalidate cache(protect burn after read paste) + window.addEventListener('popstate', () => { + window.location.reload(); + }); // display an existing paste return me.showPaste(); diff --git a/js/test/Helper.js b/js/test/Helper.js index f58d73a..2382c83 100644 --- a/js/test/Helper.js +++ b/js/test/Helper.js @@ -125,7 +125,7 @@ describe('Helper', function () { let result = e.html(); clean(); url = $('
').text(url).html(); - return $('
').text(prefix).html() + '' + url + '' + $('
').text(postfix).html() === result; + return $('
').text(prefix).html() + '' + url + '' + $('
').text(postfix).html() === result; } ); jsc.property( @@ -145,7 +145,7 @@ describe('Helper', function () { let result = e.html(); clean(); url = $('
').text(url).html(); - return $('
').text(prefix).html() + '' + url + '' + $('
').text(postfix).html() === result; + return $('
').text(prefix).html() + '' + url + '' + $('
').text(postfix).html() === result; } ); }); diff --git a/lib/Configuration.php b/lib/Configuration.php index 06edf68..4df121f 100644 --- a/lib/Configuration.php +++ b/lib/Configuration.php @@ -53,7 +53,7 @@ class Configuration 'urlshortener' => '', 'qrcode' => true, 'icon' => 'identicon', - 'cspheader' => 'default-src \'none\'; manifest-src \'self\'; connect-src * blob:; script-src \'self\' \'unsafe-eval\'; 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', + 'cspheader' => 'default-src \'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', 'zerobincompatibility' => false, 'httpwarning' => true, 'compression' => 'zlib', diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index 0b2d95a..71da5a6 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -72,7 +72,7 @@ endif; ?> - + diff --git a/tpl/page.php b/tpl/page.php index 947850e..fd13cc1 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -50,7 +50,7 @@ endif; ?> - +