mirror of
https://github.com/PrivateBin/PrivateBin.git
synced 2026-03-05 13:30:32 -05:00
Merge branch 'master' into xss/jsImprove
This commit is contained in:
@@ -10,7 +10,7 @@ global.WebCrypto = require('@peculiar/webcrypto').Crypto;
|
||||
|
||||
// application libraries to test
|
||||
global.$ = global.jQuery = require('./jquery-3.7.1');
|
||||
global.zlib = require('./zlib-1.3.1-1').zlib;
|
||||
global.zlib = require('./zlib-1.3.1-2').zlib;
|
||||
require('./prettify');
|
||||
global.prettyPrint = window.PR.prettyPrint;
|
||||
global.prettyPrintOne = window.PR.prettyPrintOne;
|
||||
@@ -82,10 +82,10 @@ function parseMime(line) {
|
||||
// these to be character encoding agnostic
|
||||
exports.atob = function(encoded) {
|
||||
return Buffer.from(encoded, 'base64').toString('binary');
|
||||
}
|
||||
};
|
||||
exports.btoa = function(text) {
|
||||
return Buffer.from(text, 'binary').toString('base64');
|
||||
}
|
||||
};
|
||||
|
||||
// provides random lowercase characters from a to z
|
||||
exports.jscA2zString = function() {
|
||||
|
||||
35
js/legacy.js
35
js/legacy.js
@@ -55,12 +55,43 @@
|
||||
* blacklist of UserAgents (parts) known to belong to a bot
|
||||
*
|
||||
* @private
|
||||
* @enum {Array}
|
||||
* @type {string[]}
|
||||
* @readonly
|
||||
*/
|
||||
var badBotUA = [
|
||||
// Generic bot identifiers
|
||||
'bot',
|
||||
'Bot',
|
||||
'bot'
|
||||
'crawler',
|
||||
'Crawler',
|
||||
'spider',
|
||||
'Spider',
|
||||
'scraper',
|
||||
'Scraper',
|
||||
|
||||
// Search Engines
|
||||
'Mediapartners-Google',
|
||||
'BingPreview',
|
||||
'Yahoo! Slurp',
|
||||
|
||||
// SEO & Analytics
|
||||
'Screaming Frog',
|
||||
|
||||
// Social Media
|
||||
'facebookexternalhit',
|
||||
|
||||
// AI & LLM
|
||||
'ChatGPT-User',
|
||||
'anthropic-ai',
|
||||
|
||||
// Security Scanners
|
||||
'CensysInspect',
|
||||
'Shodan',
|
||||
|
||||
// Other Common Crawlers
|
||||
'80legs',
|
||||
'ia_archiver',
|
||||
'Teoma',
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
17
js/package-lock.json
generated
17
js/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "privatebin",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.3",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "privatebin",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.3",
|
||||
"license": "zlib-acknowledgement",
|
||||
"devDependencies": {
|
||||
"@peculiar/webcrypto": "^1.5.0",
|
||||
@@ -1275,11 +1275,10 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
|
||||
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
},
|
||||
@@ -2785,9 +2784,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
|
||||
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^2.0.1"
|
||||
|
||||
@@ -569,13 +569,14 @@ jQuery.PrivateBin = (function($) {
|
||||
* @param {string} str
|
||||
* @return {string} escaped HTML
|
||||
*/
|
||||
me.htmlEntities = function(str) {
|
||||
me.htmlEntities = function(str)
|
||||
{
|
||||
return String(str).replace(
|
||||
/[&<>"'`=\/]/g, function(s) {
|
||||
return entityMap[s];
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* calculate expiration date given initial date and expiration period
|
||||
@@ -586,7 +587,8 @@ jQuery.PrivateBin = (function($) {
|
||||
* @param {string|number} expirationDisplayStringOrSecondsToExpire - may not be empty
|
||||
* @return {Date}
|
||||
*/
|
||||
me.calculateExpirationDate = function(initialDate, expirationDisplayStringOrSecondsToExpire) {
|
||||
me.calculateExpirationDate = function(initialDate, expirationDisplayStringOrSecondsToExpire)
|
||||
{
|
||||
let expirationDate = new Date(initialDate),
|
||||
secondsToExpiration = expirationDisplayStringOrSecondsToExpire;
|
||||
if (typeof expirationDisplayStringOrSecondsToExpire === 'string') {
|
||||
@@ -631,7 +633,7 @@ jQuery.PrivateBin = (function($) {
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* resets state, used for unit testing
|
||||
@@ -685,7 +687,7 @@ jQuery.PrivateBin = (function($) {
|
||||
* @prop {string[]}
|
||||
* @readonly
|
||||
*/
|
||||
const supportedLanguages = ['ar', 'bg', 'ca', 'co', 'cs', 'de', 'el', 'es', 'et', 'fi', 'fr', 'he', 'hu', 'id', 'it', 'ja', 'jbo', 'lt', 'no', 'nl', 'pl', 'pt', 'oc', 'ro', 'ru', 'sk', 'sl', 'th', 'tr', 'uk', 'zh'];
|
||||
const supportedLanguages = ['ar', 'bg', 'ca', 'co', 'cs', 'de', 'el', 'es', 'et', 'fa', 'fi', 'fr', 'he', 'hu', 'id', 'it', 'ja', 'jbo', 'lt', 'no', 'nl', 'pl', 'pt', 'oc', 'ro', 'ru', 'sk', 'sl', 'sv', 'th', 'tr', 'uk', 'zh'];
|
||||
|
||||
/**
|
||||
* built in language
|
||||
@@ -873,6 +875,7 @@ jQuery.PrivateBin = (function($) {
|
||||
case 'sk':
|
||||
return n === 1 ? 0 : (n >= 2 && n <= 4 ? 1 : 2);
|
||||
case 'co':
|
||||
case 'fa':
|
||||
case 'fr':
|
||||
case 'oc':
|
||||
case 'tr':
|
||||
@@ -896,7 +899,7 @@ jQuery.PrivateBin = (function($) {
|
||||
return n % 10 === 1 && n % 100 !== 11 ? 0 : (n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2);
|
||||
case 'sl':
|
||||
return n % 100 === 1 ? 1 : (n % 100 === 2 ? 2 : (n % 100 === 3 || n % 100 === 4 ? 3 : 0));
|
||||
// bg, ca, de, el, en, es, et, fi, hu, it, nl, no, pt
|
||||
// bg, ca, de, el, en, es, et, fi, hu, it, nl, no, pt, sv
|
||||
default:
|
||||
return n !== 1 ? 1 : 0;
|
||||
}
|
||||
@@ -1317,7 +1320,7 @@ jQuery.PrivateBin = (function($) {
|
||||
spec[1] = atob(spec[1]);
|
||||
if (spec[7] === 'zlib') {
|
||||
if (typeof zlib === 'undefined') {
|
||||
throw 'Error decompressing document, your browser does not support WebAssembly. Please use another browser to view this document.'
|
||||
throw 'Error decompressing document, your browser does not support WebAssembly. Please use another browser to view this document.';
|
||||
}
|
||||
}
|
||||
try {
|
||||
@@ -2997,8 +3000,9 @@ jQuery.PrivateBin = (function($) {
|
||||
attachmentLink.attr('download', fileName);
|
||||
|
||||
const fileSize = Helper.formatBytes(decodedData.length);
|
||||
const fileInfo = document.createTextNode(` (${fileName}, ${fileSize})`);
|
||||
template[0].appendChild(fileInfo);
|
||||
const spans = template[0].querySelectorAll('span');
|
||||
const span = spans[spans.length - 1];
|
||||
span.textContent += ` (${fileName}, ${fileSize})`;
|
||||
}
|
||||
|
||||
// sanitize SVG preview
|
||||
@@ -3239,7 +3243,7 @@ jQuery.PrivateBin = (function($) {
|
||||
* @param {FileList[]} loadedFiles (optional) loaded files array
|
||||
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/FileReader#readAsDataURL()}
|
||||
*/
|
||||
function readFileData(loadedFiles) {
|
||||
function readFileData(loadedFiles = []) {
|
||||
// Clear old cache
|
||||
me.removeAttachmentData();
|
||||
|
||||
@@ -3251,15 +3255,15 @@ jQuery.PrivateBin = (function($) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (loadedFiles === undefined) {
|
||||
loadedFiles = [...$fileInput[0].files];
|
||||
me.clearDragAndDrop();
|
||||
} else {
|
||||
if (loadedFiles && loadedFiles.length > 0) {
|
||||
const fileNames = loadedFiles.map((loadedFile => loadedFile.name));
|
||||
printDragAndDropFileNames(fileNames);
|
||||
} else {
|
||||
loadedFiles = [...$fileInput[0].files];
|
||||
me.clearDragAndDrop();
|
||||
}
|
||||
|
||||
if (typeof loadedFiles !== 'undefined') {
|
||||
if (loadedFiles.length > 0) {
|
||||
files = loadedFiles;
|
||||
loadedFiles.forEach((loadedFile, index) => {
|
||||
const fileReader = new FileReader();
|
||||
@@ -3404,19 +3408,21 @@ jQuery.PrivateBin = (function($) {
|
||||
* @function
|
||||
*/
|
||||
function addClipboardEventHandler() {
|
||||
$('#message').on('paste', function (event) {
|
||||
document.addEventListener('paste', (event) => {
|
||||
const items = (event.clipboardData || event.originalEvent.clipboardData).items;
|
||||
const files = [...items]
|
||||
.filter(item => item.kind === 'file')
|
||||
.map(item => item.getAsFile());
|
||||
|
||||
if (TopNav.isAttachmentReadonly()) {
|
||||
if (TopNav.isAttachmentReadonly() && files.length) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
readFileData(files);
|
||||
if (files.length) {
|
||||
readFileData(files);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4635,7 +4641,11 @@ jQuery.PrivateBin = (function($) {
|
||||
*/
|
||||
me.setFormat = function(format)
|
||||
{
|
||||
$formatter.parent().find(`a[data-format="${format}"]`).click();
|
||||
if (Helper.isBootstrap5()) {
|
||||
$formatter.find('select').val(format);
|
||||
} else {
|
||||
$formatter.parent().find(`a[data-format="${format}"]`).click();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5795,6 +5805,10 @@ jQuery.PrivateBin = (function($) {
|
||||
AttachmentViewer.removeAttachment();
|
||||
TopNav.resetInput();
|
||||
|
||||
// reset format
|
||||
PasteViewer.setFormat('plaintext');
|
||||
TopNav.setFormat('plaintext');
|
||||
|
||||
TopNav.showCreateButtons();
|
||||
|
||||
// newPaste could be called when user is on document clone editing view
|
||||
|
||||
@@ -49,7 +49,7 @@ describe('AttachmentViewer', function () {
|
||||
{value: function(blob) {
|
||||
return 'blob:' + location.origin + '/1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed';
|
||||
}}
|
||||
)
|
||||
);
|
||||
}
|
||||
$.PrivateBin.AttachmentViewer.init();
|
||||
$.PrivateBin.Model.init();
|
||||
@@ -152,7 +152,7 @@ describe('AttachmentViewer', function () {
|
||||
{value: function(blob) {
|
||||
return 'blob:' + location.origin + '/1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed';
|
||||
}}
|
||||
)
|
||||
);
|
||||
}
|
||||
$.PrivateBin.AttachmentViewer.init();
|
||||
$.PrivateBin.Model.init();
|
||||
|
||||
@@ -126,7 +126,7 @@ describe('Helper', function () {
|
||||
clean();
|
||||
urlString = $('<div />').text(urlString).html();
|
||||
const expected = $('<div />').text(prefix).html() + '<a href="' + urlString + '" target="_blank" rel="nofollow noopener noreferrer">' + urlString + '</a>' + $('<div />').text(postfix).html();
|
||||
return $('<div />').text(prefix).html() + '<a href="' + urlString + '" target="_blank" rel="nofollow noopener noreferrer">' + urlString + '</a>' + $('<div />').text(postfix).html() === result;
|
||||
return expected === result;
|
||||
}
|
||||
);
|
||||
jsc.property(
|
||||
|
||||
@@ -144,7 +144,7 @@ describe('PasteStatus', function () {
|
||||
common.jscUrl(),
|
||||
common.jscUrl(false),
|
||||
function (schema, longUrl, shortUrl) {
|
||||
const [longUrlString, shortUrlString] = urlStrings(schema, longUrl, shortUrl),
|
||||
const [_, shortUrlString] = urlStrings(schema, longUrl, shortUrl),
|
||||
yourlsResponse = '<!DOCTYPE html>\n' +
|
||||
'<html lang="en">\n' +
|
||||
'\t<head>\n' +
|
||||
|
||||
@@ -10,7 +10,7 @@ describe('Prompt', function () {
|
||||
'string',
|
||||
function (password) {
|
||||
password = password.replace(/\r+|\n+/g, '');
|
||||
const clean = jsdom('', {url: 'ftp://example.com/?0000000000000000'});
|
||||
/* const clean = */ jsdom('', {url: 'ftp://example.com/?0000000000000000'});
|
||||
$('body').html(
|
||||
'<div id="passwordmodal" class="modal fade" role="dialog">' +
|
||||
'<div class="modal-dialog"><div class="modal-content">' +
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use strict';
|
||||
var common = require('../common');
|
||||
require('../common');
|
||||
|
||||
describe('TopNav', function () {
|
||||
describe('showViewButtons & hideViewButtons', function () {
|
||||
@@ -10,7 +10,7 @@ describe('TopNav', function () {
|
||||
it(
|
||||
'displays & hides navigation elements for viewing an existing document',
|
||||
function () {
|
||||
var results = [];
|
||||
let results = [];
|
||||
$('body').html(
|
||||
'<nav class="navbar navbar-inverse navbar-static-top">' +
|
||||
'<div id="navbar" class="navbar-collapse collapse"><ul ' +
|
||||
@@ -69,7 +69,7 @@ describe('TopNav', function () {
|
||||
it(
|
||||
'displays & hides navigation elements for creating a document',
|
||||
function () { // eslint-disable-line complexity
|
||||
var results = [];
|
||||
let results = [];
|
||||
$('body').html(
|
||||
'<nav><div id="navbar"><ul><li><button id="newbutton" ' +
|
||||
'type="button" class="hidden">New</button></li><li><a ' +
|
||||
@@ -134,7 +134,7 @@ describe('TopNav', function () {
|
||||
it(
|
||||
'displays the button for creating a document',
|
||||
function () {
|
||||
var results = [];
|
||||
let results = [];
|
||||
$('body').html(
|
||||
'<nav><div id="navbar"><ul><li><button id="newbutton" type=' +
|
||||
'"button" class="hidden">New</button></li></ul></div></nav>'
|
||||
@@ -165,7 +165,7 @@ describe('TopNav', function () {
|
||||
it(
|
||||
'hides the button for cloning a document',
|
||||
function () {
|
||||
var results = [];
|
||||
let results = [];
|
||||
$('body').html(
|
||||
'<nav><div id="navbar"><ul><li><button id="clonebutton" ' +
|
||||
'type="button" class="btn btn-warning navbar-btn">' +
|
||||
@@ -198,7 +198,7 @@ describe('TopNav', function () {
|
||||
it(
|
||||
'hides the raw text button',
|
||||
function () {
|
||||
var results = [];
|
||||
let results = [];
|
||||
$('body').html(
|
||||
'<nav><div id="navbar"><ul><li><button ' +
|
||||
'id="rawtextbutton" type="button" class="btn ' +
|
||||
@@ -232,7 +232,7 @@ describe('TopNav', function () {
|
||||
it(
|
||||
'hides the file attachment selection button',
|
||||
function () {
|
||||
var results = [];
|
||||
let results = [];
|
||||
$('body').html(
|
||||
'<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
|
||||
'dropdown"><a href="#" class="dropdown-toggle" data-' +
|
||||
@@ -270,7 +270,7 @@ describe('TopNav', function () {
|
||||
it(
|
||||
'display the custom file attachment',
|
||||
function () {
|
||||
var results = [];
|
||||
let results = [];
|
||||
$('body').html(
|
||||
'<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
|
||||
'dropdown"><a href="#" class="dropdown-toggle" data-' +
|
||||
@@ -308,8 +308,8 @@ describe('TopNav', function () {
|
||||
it(
|
||||
'collapses the navigation when displayed on a small screen',
|
||||
function () {
|
||||
var clean = jsdom(),
|
||||
results = [];
|
||||
const clean = jsdom();
|
||||
let results = [];
|
||||
$('body').html(
|
||||
'<nav><div class="navbar-header"><button type="button" ' +
|
||||
'class="navbar-toggle collapsed" data-toggle="collapse" ' +
|
||||
@@ -363,7 +363,7 @@ describe('TopNav', function () {
|
||||
it(
|
||||
'reset inputs to defaults (options off)',
|
||||
function () {
|
||||
var results = [];
|
||||
let results = [];
|
||||
$('body').html(
|
||||
'<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
|
||||
'class="hidden"><label><input type="checkbox" ' +
|
||||
@@ -407,7 +407,7 @@ describe('TopNav', function () {
|
||||
it(
|
||||
'reset inputs to defaults (burnafterreading on)',
|
||||
function () {
|
||||
var results = [];
|
||||
let results = [];
|
||||
$('body').html(
|
||||
'<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
|
||||
'class="hidden"><label><input type="checkbox" ' +
|
||||
@@ -450,7 +450,7 @@ describe('TopNav', function () {
|
||||
it(
|
||||
'reset inputs to defaults (opendiscussion on)',
|
||||
function () {
|
||||
var results = [];
|
||||
let results = [];
|
||||
$('body').html(
|
||||
'<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
|
||||
'class="hidden"><label><input type="checkbox" ' +
|
||||
@@ -517,16 +517,14 @@ describe('TopNav', function () {
|
||||
cleanup();
|
||||
});
|
||||
|
||||
var File = window.File,
|
||||
const File = window.File,
|
||||
FileList = window.FileList,
|
||||
path = require('path'), // eslint-disable-line global-require
|
||||
mime = require('mime-types'); // eslint-disable-line global-require
|
||||
|
||||
// mocking file input as per https://github.com/jsdom/jsdom/issues/1272
|
||||
function createFile(file_path) {
|
||||
var file = fs.statSync(file_path),
|
||||
lastModified = file.mtimeMs,
|
||||
size = file.size;
|
||||
const lastModified = fs.statSync(file_path).mtimeMs;
|
||||
|
||||
return new File(
|
||||
[new fs.readFileSync(file_path)],
|
||||
@@ -559,7 +557,7 @@ describe('TopNav', function () {
|
||||
it(
|
||||
'returns the selected files',
|
||||
function () {
|
||||
var results = [];
|
||||
let results = [];
|
||||
$('body').html(
|
||||
'<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
|
||||
'dropdown"><a href="#" class="dropdown-toggle" data-' +
|
||||
@@ -579,7 +577,7 @@ describe('TopNav', function () {
|
||||
'../img/logo.svg',
|
||||
'../img/busy.gif'
|
||||
]);
|
||||
var files = $.PrivateBin.TopNav.getFileList();
|
||||
const files = $.PrivateBin.TopNav.getFileList();
|
||||
results.push(
|
||||
files[0].name === 'logo.svg' &&
|
||||
files[1].name === 'busy.gif'
|
||||
@@ -602,7 +600,7 @@ describe('TopNav', function () {
|
||||
it(
|
||||
'returns if the burn-after-reading checkbox was ticked',
|
||||
function () {
|
||||
var results = [];
|
||||
let results = [];
|
||||
$('body').html(
|
||||
'<nav><div id="navbar"><ul><li id="burnafterreadingoption" ' +
|
||||
'class="hidden"><label><input type="checkbox" ' +
|
||||
@@ -639,7 +637,7 @@ describe('TopNav', function () {
|
||||
it(
|
||||
'returns if the open-discussion checkbox was ticked',
|
||||
function () {
|
||||
var results = [];
|
||||
let results = [];
|
||||
$('body').html(
|
||||
'<nav><div id="navbar"><ul><li id="opendiscussionoption" ' +
|
||||
'class="hidden"><label><input type="checkbox" ' +
|
||||
@@ -678,7 +676,7 @@ describe('TopNav', function () {
|
||||
'string',
|
||||
function (password) {
|
||||
password = password.replace(/\r+|\n+/g, '');
|
||||
var results = [];
|
||||
let results = [];
|
||||
$('body').html(
|
||||
'<nav><div id="navbar"><ul><li><div id="password" ' +
|
||||
'class="navbar-form hidden"><input type="password" ' +
|
||||
@@ -715,7 +713,7 @@ describe('TopNav', function () {
|
||||
it(
|
||||
'returns the custom attachment element',
|
||||
function () {
|
||||
var results = [];
|
||||
let results = [];
|
||||
$('body').html(
|
||||
'<nav><div id="navbar"><ul><li id="attach" class="hidden ' +
|
||||
'dropdown"><a href="#" class="dropdown-toggle" data-' +
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
'use strict';
|
||||
var common = require('../common');
|
||||
const assert = require('assert');
|
||||
require('../common');
|
||||
|
||||
// DOM builder that mirrors bootstrap5.php navbar
|
||||
function buildEmailDomNoShortUrl() {
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
rawDef.destroy();
|
||||
return ret;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user