Line highlighting

This commit is contained in:
atomic-addison 2021-02-10 16:15:00 +02:00
parent 7006598d87
commit 478b83afeb
4 changed files with 409 additions and 208 deletions

View File

@ -0,0 +1,99 @@
li.line-selected,
li.line-selected-extra,
li.line-highlighted {
background: #FFF8C5 !important;
position: relative !important;
}
li .highlighter-selected {
position: absolute;
left: -52px;
display: none;
color: #5CB85C;
}
li .highlighter-controls {
position: absolute;
left: -35px;
display: none;
}
li.line-selected .highlighter-selected {
display: inline-flex;
}
li.line-selected-extra:before {
display: inline-flex;
width: 3px;
height: 19px;
background: #FF5500;
content: "";
left: -52px;
position: absolute;
}
li.line-selected .highlighter-selected .left-line {
display: inline-flex;
width: 3px;
height: 19px;
background: #FF5500;
}
li.line-highlighted .highlighter-controls {
display: inline-flex;
z-index: 999;
}
li.line-highlighted .highlighter-controls .hc-toggle {
color: #333;
background-color: #f5f5f5;
border: 1px solid #ccc;
padding: 2px 8px;
border-radius: 3px;
display: inline-flex;
cursor: pointer;
}
li.line-highlighted .highlighter-controls .hc-toggle:hover {
background-color: #E4E4E4;
}
li.line-highlighted .highlighter-controls .hc-dropdown {
display: none;
position: absolute;
color: #333;
background-color: #f5f5f5;
border: 1px solid #ccc;
padding: 2px 0;
border-radius: 3px;
left: 35px;
}
li.line-highlighted .highlighter-controls .hc-dropdown ul {
display: flex;
flex-direction: column;
padding: 0px;
margin: 0px;
list-style: none;
}
li.line-highlighted .highlighter-controls .hc-dropdown ul li {
display: inline-flex;
cursor: pointer;
white-space: nowrap;
width: 100%;
padding: 2px 8px;
}
li.line-highlighted .highlighter-controls .hc-dropdown ul li:hover {
background-color: #E4E4E4;
}
li.line-highlighted .highlighter-controls.hc-open .hc-dropdown {
display: inline-flex;
}
li.line-highlighted .highlighter-controls .hc-dropdown ul li.extend-line,
li.line-highlighted .highlighter-controls .hc-dropdown ul li.unselect-line {
display: none;
}

View File

@ -13,19 +13,24 @@
// global Base64, DOMPurify, FileReader, RawDeflate, history, navigator, prettyPrint, prettyPrintOne, showdown, kjua
var globalScrollPosition;
var globalSecondPositionMultiple;
var selectedLine;
var allowedReset = false;
jQuery.fn.draghover = function() {
'use strict';
return this.each(function() {
let collection = $(),
self = $(this);
self.on('dragenter', function(e) {
if (collection.length === 0) {
self.trigger('draghoverstart');
}
collection = collection.add(e.target);
});
self.on('dragleave drop', function(e) {
collection = collection.not(e.target);
if (collection.length === 0) {
@ -42,6 +47,187 @@ jQuery(document).ready(function() {
$.PrivateBin.Controller.init();
});
function parse_query_string(query) {
var vars = query.split("&");
var query_string = {};
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
var key = decodeURIComponent(pair[0]);
var value = decodeURIComponent(pair[1]);
// If first entry with this name
if (typeof query_string[key] === "undefined") {
query_string[key] = decodeURIComponent(value);
// If second entry with this name
} else if (typeof query_string[key] === "string") {
var arr = [query_string[key], decodeURIComponent(value)];
query_string[key] = arr;
// If third or later entry with this name
} else {
query_string[key].push(decodeURIComponent(value));
}
}
return query_string;
}
function markLines(a, b) {
for (var i = a+1; i < b+1; i++) {
$(".linenums").children().eq(i).addClass("line-selected-extra");
}
}
function selectLinesBetween() {
var a = globalScrollPosition < globalSecondPositionMultiple ? globalScrollPosition : globalSecondPositionMultiple;
var b = globalScrollPosition > globalSecondPositionMultiple ? globalScrollPosition : globalSecondPositionMultiple;
globalScrollPosition = a;
globalSecondPositionMultiple = b;
allowedReset = false;
$(".linenums").children().eq(globalScrollPosition).find(".select-line").click();
allowedReset = true;
markLines(a, b);
}
function attachLineHighlighter() {
var optsOpen = false;
if ($("#prettyprint").length < 1 || $("#prettyprint").find("li").length < 1) return;
$("#prettyprint").find("li").append(`
<div class="highlighter-controls"><div class="hc-toggle"><span class="glyphicon glyphicon-option-horizontal"></span></div><div class="hc-dropdown"><ul><li class="select-line">Scroll here</li><li class="unselect-line">Do not scroll here</li><li class="extend-line">Extend here</li></ul></div></div><div class="highlighter-selected"><span class="left-line"></span></div>
`.trim());
setTimeout(function(){
$("#prettyprint").find("li").hover(function () {
if (optsOpen) return;
$(".line-highlighted").removeClass("line-highlighted");
$(this).addClass("line-highlighted");
});
$(".hc-toggle").click(function(e) {
e.stopPropagation();
optsOpen = true;
$(this).parent().addClass("hc-open");
if (!globalScrollPosition) $(this).find(".extend-line").hide();
else {
var selectS = $(".linenums").children().eq(globalScrollPosition);
selectS.find(".extend-line").hide();
}
});
$(".hc-toggle").one("click", function() {
$(".extend-line").show();
var qs = parse_query_string(window.location.href);
if (!globalScrollPosition && !qs.s) $(".extend-line").hide();
});
$(document).on('click', function(e) {
optsOpen = false;
$(".highlighter-controls").removeClass("hc-open");
});
$(".extend-line").click(function() {
globalSecondPositionMultiple = $(this).parents("li").index();
if (!globalScrollPosition) {
var qs = parse_query_string(window.location.href);
globalScrollPosition = Number(qs.s);
}
selectLinesBetween();
var freshURL = window.location.href.split('&')[0];
if (!freshURL.includes("#")) return;
var URLA = "";
if (globalScrollPosition && globalScrollPosition!="") URLA+=`&s=${globalScrollPosition+1}`;
if (globalSecondPositionMultiple && globalSecondPositionMultiple!="") URLA+=`&e=${globalSecondPositionMultiple+1}`;
window.history.pushState('page2', 'Title', freshURL + URLA);
});
$(".select-line").click(function() {
$(".select-line").show();
$(".extend-line").show();
$(".unselect-line").hide();
$(this).hide();
$(this).siblings(".extend-line").hide();
$(this).siblings(".unselect-line").show();
globalScrollPosition = $(this).parents("li").index();
if (allowedReset) globalSecondPositionMultiple = null;
$(".line-selected").removeClass("line-selected");
$(".line-selected-extra").removeClass("line-selected-extra");
$(this).parents("li").addClass("line-selected");
optsOpen = false;
$(".highlighter-controls").removeClass("hc-open");
var freshURL = window.location.href.split('&')[0];
if (!freshURL.includes("#")) return;
var URLA = "";
if (globalScrollPosition && globalScrollPosition!="") URLA+=`&s=${globalScrollPosition+1}`;
if (globalSecondPositionMultiple && globalSecondPositionMultiple!="") URLA+=`&e=${globalSecondPositionMultiple+1}`;
window.history.pushState('page2', 'Title', freshURL + URLA);
});
$(".unselect-line").click(function() {
$(this).hide();
$(this).siblings(".select-line").show();
$(".extend-line").hide();
globalScrollPosition = null;
globalSecondPositionMultiple = null;
$(".line-selected").removeClass("line-selected");
$(".line-selected-extra").removeClass("line-selected-extra");
optsOpen = false;
$(".highlighter-controls").removeClass("hc-open");
var freshURL = window.location.href.split('&')[0];
window.history.pushState('page2', 'Title', freshURL);
});
$(document).ready(function() {
var qs = parse_query_string(window.location.href);
if (qs.s && qs.s != "") {
$(".line-selected").removeClass("line-selected");
$(".line-selected-extra").removeClass("line-selected-extra");
selectedLine = $(".linenums").children().eq(qs.s)
selectedLine.addClass("line-selected");
$(".line-selected").find(".hc-toggle").one('click', function(event) {
selectedLine.find(".unselect-line").show();
selectedLine.find(".select-line").hide();
});
if (qs.e && qs.e != "") {
markLines(Number(qs.s)-2, Number(qs.e)-1);
}
$([document.documentElement, document.body]).animate({
scrollTop: selectedLine.offset().top - 50
}, 500);
}
})
}, 150);
}
jQuery.PrivateBin = (function($, RawDeflate) {
'use strict';
@ -243,18 +429,6 @@ 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)
*
@ -338,7 +512,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)
@ -349,8 +523,6 @@ jQuery.PrivateBin = (function($, RawDeflate) {
return factor * hour;
case 'day':
return factor * day;
case 'week':
return factor * week;
case 'month':
return factor * month;
case 'year':
@ -405,11 +577,9 @@ jQuery.PrivateBin = (function($, RawDeflate) {
me.urls2links = function(element)
{
element.html(
DOMPurify.sanitize(
element.html().replace(
/(((https?|ftp):\/\/[\w?!=&.\/-;#@~%+*-]+(?![\w\s?!&.\/;#~%"=-]>))|((magnet):[\w?=&.\/-;#@~%+*-]+))/ig,
'<a href="$1" rel="nofollow noopener noreferrer">$1</a>'
)
element.html().replace(
/(((https?|ftp):\/\/[\w?!=&.\/-;#@~%+*-]+(?![\w\s?!&.\/;#~%"=-]>))|((magnet):[\w?=&.\/-;#@~%+*-]+))/ig,
'<a href="$1" rel="nofollow">$1</a>'
)
);
};
@ -535,7 +705,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
/**
* calculate expiration date given initial date and expiration period
*
*
* @name Helper.calculateExpirationDate
* @function
* @param {Date} initialDate - may not be empty
@ -548,7 +718,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
if (typeof expirationDisplayStringOrSecondsToExpire === 'string') {
secondsToExpiration = me.durationToSeconds(expirationDisplayStringOrSecondsToExpire);
}
if (typeof secondsToExpiration !== 'number') {
throw new Error('Cannot calculate expiration date.');
}
@ -601,7 +771,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
* @prop {string[]}
* @readonly
*/
const supportedLanguages = ['bg', 'cs', 'de', 'es', 'fr', 'he', 'hu', 'it', 'lt', 'no', 'nl', 'pl', 'pt', 'oc', 'ru', 'sl', 'uk', 'zh'];
const supportedLanguages = ['bg', 'cs', 'de', 'es', 'fr', 'it', 'hu', 'no', 'nl', 'pl', 'pt', 'oc', 'ru', 'sl', 'uk', 'zh'];
/**
* built in language
@ -782,10 +952,6 @@ jQuery.PrivateBin = (function($, RawDeflate) {
case 'oc':
case 'zh':
return n > 1 ? 1 : 0;
case 'he':
return n === 1 ? 0 : (n === 2 ? 1 : ((n < 0 || n > 10) && (n % 10 === 0) ? 2 : 3));
case 'lt':
return n % 10 === 1 && n % 100 !== 11 ? 0 : ((n % 10 >= 2 && n % 100 < 10 || n % 100 >= 20) ? 1 : 2);
case 'pl':
return n === 1 ? 0 : (n % 10 >= 2 && n %10 <=4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2);
case 'ru':
@ -1995,11 +2161,19 @@ jQuery.PrivateBin = (function($, RawDeflate) {
return a.length - b.length;
})[0];
if (typeof shortUrl === 'string' && shortUrl.length > 0) {
var URLA = "";
if (globalScrollPosition && globalScrollPosition!="") URLA+=`&s=${globalScrollPosition+1}`;
if (globalSecondPositionMultiple && globalSecondPositionMultiple!="") URLA+=`&e=${globalSecondPositionMultiple+1}`;
I18n._(
$('#pastelink'),
`Your paste is <a id="pasteurl" href="%s${URLA}">%s${URLA}</a> <span id="copyhint">(Hit [Ctrl]+[c] to copy)</span>`,
shortUrl, shortUrl
);
// we disable the button to avoid calling shortener again
$shortenButton.addClass('buttondisabled');
// update link
$pasteUrl.text(shortUrl);
$pasteUrl.prop('href', shortUrl);
// save newly created element
$pasteUrl = $('#pasteurl');
// we pre-select the link so that the user only has to [Ctrl]+[c] the link
Helper.selectText($pasteUrl[0]);
return;
@ -2049,9 +2223,13 @@ jQuery.PrivateBin = (function($, RawDeflate) {
*/
me.createPasteNotification = function(url, deleteUrl)
{
var URLA = "";
if (globalScrollPosition && globalScrollPosition!="") URLA+=`&s=${globalScrollPosition+1}`;
if (globalSecondPositionMultiple && globalSecondPositionMultiple!="") URLA+=`&e=${globalSecondPositionMultiple+1}`;
I18n._(
$('#pastelink'),
'Your paste is <a id="pasteurl" href="%s">%s</a> <span id="copyhint">(Hit [Ctrl]+[c] to copy)</span>',
`Your paste is <a id="pasteurl" href="%s${URLA}">%s${URLA}</a> <span id="copyhint">(Hit [Ctrl]+[c] to copy)</span>`,
url, url
);
// save newly created element
@ -2420,7 +2598,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
/**
* hides the Editor
*
* @name Editor.hide
* @name Editor.reset
* @function
*/
me.hide = function()
@ -2550,6 +2728,8 @@ jQuery.PrivateBin = (function($, RawDeflate) {
Helper.htmlEntities(text), null, true
)
);
attachLineHighlighter();
} else {
// = 'plaintext'
$prettyPrint.text(text);
@ -2767,8 +2947,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
// extract mediaType
const mediaType = attachmentData.substring(5, mediaTypeEnd);
// extract data and convert to binary
const rawData = attachmentData.substring(base64Start);
const decodedData = rawData.length > 0 ? atob(rawData) : '';
const decodedData = atob(attachmentData.substring(base64Start));
// Transform into a Blob
const buf = new Uint8Array(decodedData.length);
@ -3127,15 +3306,19 @@ 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;
const lastItem = items[items.length - 1];
if (lastItem.kind === 'file') {
if (TopNav.isAttachmentReadonly()) {
event.stopPropagation();
event.preventDefault();
return false;
} else {
readFileData(lastItem.getAsFile());
for (let i = 0; i < items.length; ++i) {
if (items[i].kind === 'file') {
//Clear the file input:
$fileInput.wrap('<form>').closest('form').get(0).reset();
$fileInput.unwrap();
readFileData(items[i].getAsFile());
}
}
});
@ -3614,20 +3797,6 @@ jQuery.PrivateBin = (function($, RawDeflate) {
}
}
/**
* Clear the attachment input in the top navigation.
*
* @name TopNav.clearAttachmentInput
* @function
*/
function clearAttachmentInput()
{
// hide UI for selected files
// our up-to-date jQuery can handle it :)
$fileWrap.find('input').val('');
}
/**
* return raw text
*
@ -3722,7 +3891,9 @@ jQuery.PrivateBin = (function($, RawDeflate) {
// in any case, remove saved attachment data
AttachmentViewer.removeAttachmentData();
clearAttachmentInput();
// hide UI for selected files
// our up-to-date jQuery can handle it :)
$fileWrap.find('input').val('');
AttachmentViewer.clearDragAndDrop();
// pevent '#' from appearing in the URL
@ -3747,11 +3918,11 @@ jQuery.PrivateBin = (function($, RawDeflate) {
/**
* Template Email body.
*
*
* @name TopNav.templateEmailBody
* @private
* @param {string} expirationDateString
* @param {bool} isBurnafterreading
* @private
* @param {string} expirationDateString
* @param {bool} isBurnafterreading
*/
function templateEmailBody(expirationDateString, isBurnafterreading)
{
@ -3765,12 +3936,8 @@ jQuery.PrivateBin = (function($, RawDeflate) {
if (expirationDateString !== null) {
emailBody += EOL;
emailBody += BULLET;
// avoid DOMPurify mess with forward slash in expirationDateString
emailBody += Helper.sprintf(
I18n._(
'This link will expire after %s.',
'%s'
),
emailBody += I18n._(
'This link will expire after %s.',
expirationDateString
);
}
@ -3793,10 +3960,10 @@ jQuery.PrivateBin = (function($, RawDeflate) {
/**
* Trigger Email send.
*
*
* @name TopNav.triggerEmailSend
* @private
* @param {string} emailBody
* @private
* @param {string} emailBody
*/
function triggerEmailSend(emailBody)
{
@ -4009,7 +4176,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
/**
* show the "email" button
*
*
* @name TopNav.showEmailbutton
* @function
* @param {int|undefined} optionalRemainingTimeInSeconds
@ -4037,7 +4204,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
/**
* hide the "email" button
*
*
* @name TopNav.hideEmailButton
* @function
*/
@ -4071,7 +4238,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
/**
* only hides the qr code button
*
*
* @name TopNav.hideQrCodeButton
* @function
*/
@ -4082,7 +4249,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
/**
* hide all irrelevant buttons when viewing burn after reading paste
*
*
* @name TopNav.hideBurnAfterReadingButtons
* @function
*/
@ -4118,7 +4285,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
/**
* hides the custom attachment
*
*
* @name TopNav.hideCustomAttachment
* @function
*/
@ -4141,24 +4308,6 @@ jQuery.PrivateBin = (function($, RawDeflate) {
}
};
/**
* Reset the top navigation back to it's default values.
*
* @name TopNav.resetInput
* @function
*/
me.resetInput = function()
{
clearAttachmentInput();
$openDiscussion.prop('checked', false);
$burnAfterReading.prop('checked', false);
$openDiscussionOption.removeClass('buttondisabled');
$burnAfterReadingOption.removeClass('buttondisabled');
// TODO: reset expiration time
};
/**
* returns the currently set expiration time
*
@ -4260,7 +4409,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
/**
* Highlight file upload
*
*
* @name TopNav.highlightFileupload
* @function
*/
@ -4279,7 +4428,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
/**
* set the format on bootstrap templates in dropdown programmatically
*
*
* @name TopNav.setFormat
* @function
*/
@ -4290,14 +4439,14 @@ jQuery.PrivateBin = (function($, RawDeflate) {
/**
* returns if attachment dropdown is readonly, not editable
*
*
* @name TopNav.isAttachmentReadonly
* @function
* @return {bool}
*/
me.isAttachmentReadonly = function()
{
return !createButtonsDisplayed || $attach.hasClass('hidden');
return createButtonsDisplayed && $attach.hasClass('hidden');
}
/**
@ -5180,7 +5329,6 @@ jQuery.PrivateBin = (function($, RawDeflate) {
Editor.show();
Editor.focusInput();
AttachmentViewer.removeAttachment();
TopNav.resetInput();
TopNav.showCreateButtons();
@ -5345,23 +5493,6 @@ 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({
@ -5393,12 +5524,6 @@ 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();
@ -5407,10 +5532,11 @@ jQuery.PrivateBin = (function($, RawDeflate) {
return me.newPaste();
}
// always reload on back button to invalidate cache(protect burn after read paste)
window.addEventListener('popstate', () => {
window.location.reload();
});
// if delete token is passed (i.e. paste has been deleted by this
// access), there is nothing more to do
if (Model.hasDeleteToken()) {
return;
}
// display an existing paste
return me.showPaste();

View File

@ -13,7 +13,7 @@ $isPage = substr($template, -5) === '-page';
<meta name="google" content="notranslate">
<title><?php echo I18n::_($NAME); ?></title>
<?php
if (!$isDark) :
if (!$isDark):
?>
<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-3.4.1.css" />
<?php
@ -21,7 +21,7 @@ endif;
?>
<link type="text/css" rel="stylesheet" href="css/bootstrap/bootstrap-theme-3.4.1.css" />
<?php
if ($isDark) :
if ($isDark):
?>
<link type="text/css" rel="stylesheet" href="css/bootstrap/darkstrap-0.9.3.css" />
<?php
@ -29,11 +29,11 @@ endif;
?>
<link type="text/css" rel="stylesheet" href="css/bootstrap/privatebin.css?<?php echo rawurlencode($VERSION); ?>" />
<?php
if ($SYNTAXHIGHLIGHTING) :
if ($SYNTAXHIGHLIGHTING):
?>
<link type="text/css" rel="stylesheet" href="css/prettify/prettify.css?<?php echo rawurlencode($VERSION); ?>" />
<?php
if (strlen($SYNTAXHIGHLIGHTINGTHEME)) :
if (strlen($SYNTAXHIGHLIGHTINGTHEME)):
?>
<link type="text/css" rel="stylesheet" href="css/prettify/<?php echo rawurlencode($SYNTAXHIGHLIGHTINGTHEME); ?>.css?<?php echo rawurlencode($VERSION); ?>" />
<?php
@ -43,12 +43,12 @@ endif;
<noscript><link type="text/css" rel="stylesheet" href="css/noscript.css" /></noscript>
<script type="text/javascript" data-cfasync="false" src="js/jquery-3.4.1.js" integrity="sha512-bnIvzh6FU75ZKxp0GXLH9bewza/OIw6dLVh9ICg0gogclmYGguQJWl8U30WpbsGTqbIiAwxTsbe76DErLq5EDQ==" crossorigin="anonymous"></script>
<?php
if ($QRCODE) :
if ($QRCODE):
?>
<script async type="text/javascript" data-cfasync="false" src="js/kjua-0.6.0.js" integrity="sha512-GEEIHvphDt1NmaxzX8X1ZkBiGKXCv+Ofzwi8SMEH5wQVWqdGIvBO/fnxxKZ90RU1bVp6srS68nHIpZo6iVcG9g==" crossorigin="anonymous"></script>
<?php
endif;
if ($ZEROBINCOMPATIBILITY) :
if ($ZEROBINCOMPATIBILITY):
?>
<script type="text/javascript" data-cfasync="false" src="js/base64-1.7.js" integrity="sha512-JdwsSP3GyHR+jaCkns9CL9NTt4JUJqm/BsODGmYhBcj5EAPKcHYh+OiMfyHbcDLECe17TL0hjXADFkusAqiYgA==" crossorigin="anonymous"></script>
<?php
@ -59,41 +59,29 @@ endif;
<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.3.7.js" integrity="sha512-iztkobsvnjKfAtTNdHkGVjAYTrrtlC7mGp/54c40wowO7LhURYl3gVzzcEqGl/qKXQltJ2HwMrdLcNUdo+N/RQ==" crossorigin="anonymous"></script>
<?php
if ($SYNTAXHIGHLIGHTING) :
if ($SYNTAXHIGHLIGHTING):
?>
<script type="text/javascript" data-cfasync="false" src="js/prettify.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==" crossorigin="anonymous"></script>
<?php
endif;
if ($MARKDOWN) :
if ($MARKDOWN):
?>
<script type="text/javascript" data-cfasync="false" src="js/showdown-1.9.1.js" integrity="sha512-nRri7kqh3iRLdHbhtjfe8w9eAQPmt+ubH5U88UZyKbz6O9Q0q4haaXF0krOUclKmRJou/kKZYulgBHvHXPqOvg==" crossorigin="anonymous"></script>
<?php
endif;
?>
<script type="text/javascript" data-cfasync="false" src="js/purify-2.0.14.js" integrity="sha512-kbLhjIj/m/AW++o2eErCfqPueoX2btJo7VznhEC2YQRbVR/+Eup3w7thwDZwoCZ/gLrPxTX3W4H2KzupLg2PKA==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/purify-2.0.8.js" integrity="sha512-QwcEKGuEmKtMguCO9pqNtUtZqq9b/tJ8gNr5qhY8hykq3zKTlDOvpZAmf6Rs8yH35Bz1ZdctUjj2qEWxT5aXCg==" 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-Xri4TBGLGEpnGQLZeHAxvWq3LNQOl7wVN3jTGqQH2AG7G4ZOK+0WyZ6Isye+aOHGVkzAfOCWMW78KVlSISthkg==" crossorigin="anonymous"></script>
<!-- icon -->
<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-16x16.png" sizes="16x16" />
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha384-7ga/YvVNKP8F3uLCcuDEGNmn6ti1i8xZCMU6i+6krplcv40l55X9pjikrrt9nba+" crossorigin="anonymous"></script>
<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-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" />
<link rel="manifest" href="manifest.json?<?php echo rawurlencode($VERSION); ?>" />
<link rel="mask-icon" href="img/safari-pinned-tab.svg" color="#ffcc00" />
<link rel="mask-icon" href="img/safari-pinned-tab.svg?<?php echo rawurlencode($VERSION); ?>" color="#ffcc00" />
<link rel="shortcut icon" href="img/favicon.ico">
<meta name="msapplication-config" content="browserconfig.xml">
<meta name="theme-color" content="#ffe57e" />
<!-- Twitter/social media cards -->
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="<?php echo I18n::_('Encrypted note on PrivateBin') ?>" />
<meta name="twitter:description" content="<?php echo I18n::_('Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.') ?>" />
<meta name="twitter:image" content="<?php echo I18n::encode($BASEPATH); ?>img/apple-touch-icon.png" />
<meta property="og:title" content="<?php echo I18n::_($NAME); ?>" />
<meta property="og:site_name" content="<?php echo I18n::_($NAME); ?>" />
<meta property="og:description" content="<?php echo I18n::_('Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.') ?>" />
<meta property="og:image" content="<?php echo I18n::encode($BASEPATH); ?>img/apple-touch-icon.png" />
<meta property="og:image:type" content="image/png" />
<meta property="og:image:width" content="180" />
<meta property="og:image:height" content="180" />
<link type="text/css" rel="stylesheet" href="css/custom_linehighlighting.css?<?php echo rawurlencode($VERSION); ?>" />
</head>
<body role="document" data-compression="<?php echo rawurlencode($COMPRESSION); ?>"<?php
$class = array();
@ -123,7 +111,7 @@ if (count($class)) {
</div>
</div>
<?php
if ($QRCODE) :
if ($QRCODE):
?>
<div id="qrcodemodal" tabindex="-1" class="modal fade" aria-labelledby="qrcodemodalTitle" role="dialog" aria-hidden="true">
<div class="modal-dialog" role="document">
@ -167,7 +155,7 @@ endif;
</div>
</div>
<nav class="navbar navbar-<?php echo $isDark ? 'inverse' : 'default'; ?> navbar-<?php echo $isCpct ? 'fixed' : 'static'; ?>-top"><?php
if ($isCpct) :
if ($isCpct):
?><div class="container"><?php
endif;
?>
@ -195,11 +183,11 @@ endif;
</li>
<li>
<?php
if ($isPage) :
if ($isPage):
?>
<button id="sendbutton" type="button" class="hidden btn btn-<?php echo $isDark ? 'warning' : 'primary'; ?> navbar-btn">
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo I18n::_('Send'), PHP_EOL;
else :
else:
?>
<button id="newbutton" type="button" class="hidden btn btn-<?php echo $isDark ? 'warning' : 'default'; ?> navbar-btn">
<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo I18n::_('New'), PHP_EOL;
@ -216,7 +204,7 @@ endif;
<span class="glyphicon glyphicon-envelope" aria-hidden="true"></span> <?php echo I18n::_('Email'), PHP_EOL; ?>
</button>
<?php
if ($QRCODE) :
if ($QRCODE):
?>
<button id="qrcodelink" type="button" data-toggle="modal" data-target="#qrcodemodal" class="hidden btn btn-<?php echo $isDark ? 'warning' : 'default'; ?> navbar-btn">
<span class="glyphicon glyphicon-qrcode" aria-hidden="true"></span> <?php echo I18n::_('QR code'), PHP_EOL; ?>
@ -228,10 +216,10 @@ endif;
<li class="dropdown">
<select id="pasteExpiration" name="pasteExpiration" class="hidden">
<?php
foreach ($EXPIRE as $key => $value) :
foreach ($EXPIRE as $key => $value):
?>
<option value="<?php echo $key; ?>"<?php
if ($key == $EXPIREDEFAULT) :
if ($key == $EXPIREDEFAULT):
?> selected="selected"<?php
endif;
?>><?php echo $value; ?></option>
@ -242,7 +230,7 @@ endforeach;
<a id="expiration" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Expires'); ?>: <span id="pasteExpirationDisplay"><?php echo $EXPIRE[$EXPIREDEFAULT]; ?></span> <span class="caret"></span></a>
<ul class="dropdown-menu">
<?php
foreach ($EXPIRE as $key => $value) :
foreach ($EXPIRE as $key => $value):
?>
<li>
<a href="#" data-expiration="<?php echo $key; ?>">
@ -255,7 +243,7 @@ endforeach;
</ul>
</li>
<?php
if ($isCpct) :
if ($isCpct):
?>
<li class="dropdown">
<a id="formatter" href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Options'); ?> <span class="caret"></span></a>
@ -263,7 +251,7 @@ if ($isCpct) :
<li id="burnafterreadingoption" class="checkbox hidden">
<label>
<input type="checkbox" id="burnafterreading" name="burnafterreading"<?php
if ($BURNAFTERREADINGSELECTED) :
if ($BURNAFTERREADINGSELECTED):
?> checked="checked"<?php
endif;
?> />
@ -271,12 +259,12 @@ if ($isCpct) :
</label>
</li>
<?php
if ($DISCUSSION) :
if ($DISCUSSION):
?>
<li id="opendiscussionoption" class="checkbox hidden">
<label>
<input type="checkbox" id="opendiscussion" name="opendiscussion"<?php
if ($OPENDISCUSSION) :
if ($OPENDISCUSSION):
?> checked="checked"<?php
endif;
?> />
@ -293,7 +281,7 @@ if ($isCpct) :
</div>
</li>
<?php
foreach ($FORMATTER as $key => $value) :
foreach ($FORMATTER as $key => $value):
?>
<li>
<a href="#" data-format="<?php echo $key; ?>">
@ -306,10 +294,10 @@ if ($isCpct) :
</ul>
<select id="pasteFormatter" name="pasteFormatter" class="hidden">
<?php
foreach ($FORMATTER as $key => $value) :
foreach ($FORMATTER as $key => $value):
?>
<option value="<?php echo $key; ?>"<?php
if ($key == $FORMATTERDEFAULT) :
if ($key == $FORMATTERDEFAULT):
?> selected="selected"<?php
endif;
?>><?php echo $value; ?></option>
@ -319,13 +307,13 @@ if ($isCpct) :
</select>
</li>
<?php
else :
else:
?>
<li>
<div id="burnafterreadingoption" class="navbar-text checkbox hidden">
<label>
<input type="checkbox" id="burnafterreading" name="burnafterreading"<?php
if ($BURNAFTERREADINGSELECTED) :
if ($BURNAFTERREADINGSELECTED):
?> checked="checked"<?php
endif;
?> />
@ -334,13 +322,13 @@ else :
</div>
</li>
<?php
if ($DISCUSSION) :
if ($DISCUSSION):
?>
<li>
<div id="opendiscussionoption" class="navbar-text checkbox hidden">
<label>
<input type="checkbox" id="opendiscussion" name="opendiscussion"<?php
if ($OPENDISCUSSION) :
if ($OPENDISCUSSION):
?> checked="checked"<?php
endif;
?> />
@ -351,7 +339,7 @@ else :
<?php
endif;
endif;
if ($PASSWORD) :
if ($PASSWORD):
?>
<li>
<div id="password" class="navbar-form hidden">
@ -360,7 +348,7 @@ if ($PASSWORD) :
</li>
<?php
endif;
if ($FILEUPLOAD) :
if ($FILEUPLOAD):
?>
<li id="attach" class="hidden dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Attach a file'); ?> <span class="caret"></span></a>
@ -381,15 +369,15 @@ if ($FILEUPLOAD) :
</li>
<?php
endif;
if (!$isCpct) :
if (!$isCpct):
?>
<li class="dropdown">
<select id="pasteFormatter" name="pasteFormatter" class="hidden">
<?php
foreach ($FORMATTER as $key => $value) :
foreach ($FORMATTER as $key => $value):
?>
<option value="<?php echo $key; ?>"<?php
if ($key == $FORMATTERDEFAULT) :
if ($key == $FORMATTERDEFAULT):
?> selected="selected"<?php
endif;
?>><?php echo $value; ?></option>
@ -400,7 +388,7 @@ if (!$isCpct) :
<a id="formatter" href="#" class="hidden dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><?php echo I18n::_('Format'); ?>: <span id="pasteFormatterDisplay"><?php echo $FORMATTER[$FORMATTERDEFAULT]; ?></span> <span class="caret"></span></a>
<ul class="dropdown-menu">
<?php
foreach ($FORMATTER as $key => $value) :
foreach ($FORMATTER as $key => $value):
?>
<li>
<a href="#" data-format="<?php echo $key; ?>">
@ -418,13 +406,13 @@ endif;
</ul>
<ul class="nav navbar-nav pull-right">
<?php
if (strlen($LANGUAGESELECTION)) :
if (strlen($LANGUAGESELECTION)):
?>
<li id="language" class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-flag" aria-hidden="true"></span> <?php echo $LANGUAGES[$LANGUAGESELECTION][0]; ?> <span class="caret"></span></a>
<ul class="dropdown-menu dropdown-menu-right">
<ul class="dropdown-menu">
<?php
foreach ($LANGUAGES as $key => $value) :
foreach ($LANGUAGES as $key => $value):
?>
<li>
<a href="#" data-lang="<?php echo $key; ?>">
@ -442,14 +430,14 @@ endif;
</ul>
</div>
<?php
if ($isCpct) :
if ($isCpct):
?></div><?php
endif;
?></nav>
<main>
<section class="container">
<?php
if (strlen($NOTICE)) :
if (strlen($NOTICE)):
?>
<div role="alert" class="alert alert-info">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
@ -462,7 +450,7 @@ endif;
<span class="glyphicon glyphicon-fire" aria-hidden="true"></span>
</div>
<?php
if ($FILEUPLOAD) :
if ($FILEUPLOAD):
?>
<div id="attachment" role="alert" class="hidden alert alert-info">
<span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span>
@ -494,7 +482,7 @@ endif;
<span class="small"><?php echo I18n::_('For more information <a href="%s">see this FAQ entry</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-it-show-me-the-error-privatebin-requires-a-modern-browser-to-work'); ?></span>
</div>
<?php
if ($HTTPWARNING) :
if ($HTTPWARNING):
?>
<div id="httpnotice" role="alert" class="hidden alert alert-danger">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
@ -515,7 +503,7 @@ endif;
<div id="pastelink"></div>
</div>
<?php
if (strlen($URLSHORTENER)) :
if (strlen($URLSHORTENER)):
?>
<p>
<button id="shortenbutton" data-shortener="<?php echo I18n::encode($URLSHORTENER); ?>" type="button" class="btn btn-<?php echo $isDark ? 'warning' : 'primary'; ?> btn-block">
@ -535,11 +523,11 @@ endif;
<li role="presentation"><a role="tab" aria-selected="false" aria-controls="editorTabs" id="messagepreview" href="#"><?php echo I18n::_('Preview'); ?></a></li>
<li role="presentation" class="pull-right">
<?php
if ($isPage) :
if ($isPage):
?>
<button id="newbutton" type="button" class="reloadlink hidden btn btn-<?php echo $isDark ? 'warning' : 'default'; ?>">
<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo I18n::_('New'), PHP_EOL;
else :
else:
?>
<button id="sendbutton" type="button" class="hidden btn btn-<?php echo $isDark ? 'warning' : 'primary'; ?>">
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo I18n::_('Send'), PHP_EOL;
@ -578,13 +566,13 @@ endif;
<h4 class="col-md-5 col-xs-8"><?php echo I18n::_($NAME); ?> <small>- <?php echo I18n::_('Because ignorance is bliss'); ?></small></h4>
<p class="col-md-1 col-xs-4 text-center"><?php echo $VERSION; ?></p>
<p id="aboutbox" class="col-md-6 col-xs-12">
<?php echo I18n::_('%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES.', I18n::_($NAME)), ' ', $INFO, PHP_EOL; ?>
<?php echo I18n::_('%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://privatebin.info/">project page</a>.', I18n::_($NAME)), PHP_EOL; ?>
</p>
</div>
</footer>
</main>
<?php
if ($DISCUSSION) :
if ($DISCUSSION):
?>
<div id="serverdata" class="hidden" aria-hidden="true">
<div id="templates">
@ -597,7 +585,7 @@ if ($DISCUSSION) :
endif;
?>
<?php
if ($FILEUPLOAD) :
if ($FILEUPLOAD):
?>
<div id="dropzone" class="hidden" tabindex="-1" aria-hidden="true"></div>
<?php

View File

@ -48,10 +48,9 @@ if ($MARKDOWN):
<?php
endif;
?>
<script type="text/javascript" data-cfasync="false" src="js/purify-2.0.14.js" integrity="sha512-kbLhjIj/m/AW++o2eErCfqPueoX2btJo7VznhEC2YQRbVR/+Eup3w7thwDZwoCZ/gLrPxTX3W4H2KzupLg2PKA==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/purify-2.0.8.js" integrity="sha512-QwcEKGuEmKtMguCO9pqNtUtZqq9b/tJ8gNr5qhY8hykq3zKTlDOvpZAmf6Rs8yH35Bz1ZdctUjj2qEWxT5aXCg==" 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-Xri4TBGLGEpnGQLZeHAxvWq3LNQOl7wVN3jTGqQH2AG7G4ZOK+0WyZ6Isye+aOHGVkzAfOCWMW78KVlSISthkg==" crossorigin="anonymous"></script>
<!-- icon -->
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha384-7ga/YvVNKP8F3uLCcuDEGNmn6ti1i8xZCMU6i+6krplcv40l55X9pjikrrt9nba+" crossorigin="anonymous"></script>
<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-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" />
@ -60,23 +59,12 @@ endif;
<link rel="shortcut icon" href="img/favicon.ico">
<meta name="msapplication-config" content="browserconfig.xml">
<meta name="theme-color" content="#ffe57e" />
<!-- Twitter/social media cards -->
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="<?php echo I18n::_('Encrypted note on PrivateBin') ?>" />
<meta name="twitter:description" content="<?php echo I18n::_('Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.') ?>" />
<meta name="twitter:image" content="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" />
<meta property="og:title" content="<?php echo I18n::_($NAME); ?>" />
<meta property="og:site_name" content="<?php echo I18n::_($NAME); ?>" />
<meta property="og:description" content="<?php echo I18n::_('Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.') ?>" />
<meta property="og:image" content="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" />
<meta property="og:image:type" content="image/png" />
<meta property="og:image:width" content="180" />
<meta property="og:image:height" content="180" />
<link type="text/css" rel="stylesheet" href="css/custom_linehighlighting.css?<?php echo rawurlencode($VERSION); ?>" />
</head>
<body data-compression="<?php echo rawurlencode($COMPRESSION); ?>">
<header>
<div id="aboutbox">
<?php echo I18n::_('%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES.', I18n::_($NAME)), ' ', $INFO; ?><br />
<?php echo I18n::_('%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href="https://privatebin.info/">project page</a>.', I18n::_($NAME)); ?><br />
<?php
if (strlen($NOTICE)):
?>