diff --git a/CHANGELOG.md b/CHANGELOG.md
index d860e72b..29d2d74c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,8 @@
# PrivateBin version history
## 2.0.2 (not yet released)
+* CHANGED: Refactored jQuery DOM element creation into plain JavaScript
+* FIXED: Sanitize file name in attachment size hint
## 2.0.1 (2025-10-12)
* ADDED: Auto shorten URLs with config option `shortenbydefault` (#1627)
diff --git a/js/privatebin.js b/js/privatebin.js
index 742abb42..b96407ca 100644
--- a/js/privatebin.js
+++ b/js/privatebin.js
@@ -2992,7 +2992,8 @@ jQuery.PrivateBin = (function($) {
attachmentLink.attr('download', fileName);
const fileSize = Helper.formatBytes(decodedData.length);
- template.append(`(${fileName}, ${fileSize})`);
+ const fileInfo = document.createTextNode(` (${fileName}, ${fileSize})`);
+ template[0].appendChild(fileInfo);
}
// sanitize SVG preview
@@ -3287,44 +3288,38 @@ jQuery.PrivateBin = (function($) {
const alreadyIncludesCurrentAttachment = $targetElement.find(`[src='${blobUrl}']`).length > 0;
if (blobUrl && !alreadyIncludesCurrentAttachment) {
- if (mimeType.match(/^image\//i)) {
- $targetElement.append(
- $(document.createElement('img'))
- .attr('src', blobUrl)
- .attr('class', 'img-thumbnail')
- );
- } else if (mimeType.match(/^video\//i)) {
- $targetElement.append(
- $(document.createElement('video'))
- .attr('controls', 'true')
- .attr('autoplay', 'true')
- .attr('class', 'img-thumbnail')
-
- .append($(document.createElement('source'))
- .attr('type', mimeType)
- .attr('src', blobUrl))
- );
- } else if (mimeType.match(/^audio\//i)) {
- $targetElement.append(
- $(document.createElement('audio'))
- .attr('controls', 'true')
- .attr('autoplay', 'true')
-
- .append($(document.createElement('source'))
- .attr('type', mimeType)
- .attr('src', blobUrl))
- );
- } else if (mimeType.match(/\/pdf/i)) {
+ if (mimeType.toLowerCase().startsWith('image/')) {
+ const image = document.createElement('img');
+ image.setAttribute('src', blobUrl);
+ image.setAttribute('class', 'img-thumbnail');
+ $targetElement[0].appendChild(image);
+ } else if (mimeType.toLowerCase().startsWith('video/')) {
+ const video = document.createElement('video');
+ video.setAttribute('controls', 'true');
+ video.setAttribute('autoplay', 'true');
+ video.setAttribute('class', 'img-thumbnail');
+ const source = document.createElement('source');
+ source.setAttribute('type', mimeType);
+ source.setAttribute('src', blobUrl);
+ video.appendChild(source);
+ $targetElement[0].appendChild(video);
+ } else if (mimeType.toLowerCase().startsWith('audio/')) {
+ const audio = document.createElement('audio');
+ audio.setAttribute('controls', 'true');
+ audio.setAttribute('autoplay', 'true');
+ const source = document.createElement('source');
+ source.setAttribute('type', mimeType);
+ source.setAttribute('src', blobUrl);
+ audio.appendChild(source);
+ $targetElement[0].appendChild(audio);
+ } else if (mimeType.toLowerCase().endsWith('/pdf')) {
+ const embed = document.createElement('embed');
+ embed.setAttribute('src', blobUrl);
+ embed.setAttribute('type', 'application/pdf');
+ embed.setAttribute('class', 'pdfPreview');
// Fallback for browsers, that don't support the vh unit
- const clientHeight = $(window).height();
-
- $targetElement.append(
- $(document.createElement('embed'))
- .attr('src', blobUrl)
- .attr('type', 'application/pdf')
- .attr('class', 'pdfPreview')
- .css('height', clientHeight)
- );
+ embed.style.height = window.innerHeight + 'px';
+ $targetElement[0].appendChild(embed);
}
}
};
@@ -3603,8 +3598,9 @@ jQuery.PrivateBin = (function($) {
if (nickname.length > 0) {
$commentEntry.find('span.nickname').text(nickname);
} else {
- $commentEntry.find('span.nickname').html('');
- I18n._($commentEntry.find('span.nickname i'), 'Anonymous');
+ const anonCommenter = document.createElement('em');
+ anonCommenter.textContent = I18n._('Anonymous');
+ $commentEntry.find('span.nickname')[0].appendChild(anonCommenter);
}
// set date
@@ -3617,14 +3613,10 @@ jQuery.PrivateBin = (function($) {
// if an avatar is available, display it
const icon = comment.getIcon();
if (icon) {
- $commentEntry.find('span.nickname')
- .before(
- '
'
- );
- $(document).on('languageLoaded', function () {
- $commentEntry.find('img.vizhash')
- .prop('title', I18n._('Avatar generated from IP address'));
- });
+ const image = document.createElement('img');
+ image.setAttribute('src', icon);
+ image.setAttribute('class', 'vizhash');
+ $commentEntry.find('span.nickname').prepend(image);
}
// starting point (default value/fallback)
@@ -5418,6 +5410,10 @@ jQuery.PrivateBin = (function($) {
plaintexts[i][1]
);
}
+ $(document).on('languageLoaded', function () {
+ $('#commentcontainer').find('img.vizhash')
+ .prop('title', I18n._('Avatar generated from IP address'));
+ });
});
}
diff --git a/lib/Configuration.php b/lib/Configuration.php
index 64e495a2..9af448d9 100644
--- a/lib/Configuration.php
+++ b/lib/Configuration.php
@@ -121,7 +121,7 @@ class Configuration
'js/kjua-0.10.0.js' => 'sha512-BYj4xggowR7QD150VLSTRlzH62YPfhpIM+b/1EUEr7RQpdWAGKulxWnOvjFx1FUlba4m6ihpNYuQab51H6XlYg==',
'js/legacy.js' => 'sha512-rGXYUpIqbFoHAgBXZ0UlJBdNAIMOC9EQ67MG0X46D5uRB8LvwzgKirbSQRGdYfk8I2jsUcm+tvHXYboUnC6DUg==',
'js/prettify.js' => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==',
- 'js/privatebin.js' => 'sha512-2F02E/UQoQyCNk0FvwaOLD9MvDhtuYqTtGKdqwsbDjY4O0jMZjn/EtiP2wvS0uxYojkxeUitF0HWb+RDFUwQXg==',
+ 'js/privatebin.js' => 'sha512-7b9PUe3bhiZAjMlNMuRMLkiiTx4CpIlh/L/XAfj+zmQ0DUFXIVkdliOLEZixXliYc3N97OOZEJPpRA7VYMLyjw==',
'js/purify-3.2.7.js' => 'sha512-2H9wzIiPQCOsh7T3hK/WuqWIwSQ2oYq91doyrp1LcnXuPyxzehopypz16wiWqxmMjx2cVIqAWCoRp1gNZAsFEQ==',
'js/showdown-2.1.0.js' => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==',
'js/zlib-1.3.1-1.js' => 'sha512-5bU9IIP4PgBrOKLZvGWJD4kgfQrkTz8Z3Iqeu058mbQzW3mCumOU6M3UVbVZU9rrVoVwaW4cZK8U8h5xjF88eQ==',