
- Fixed a bug that caused encrypted uploads with no file to crash the server, as we tried to decrypt a non-existent file - Changed wording on pasta auth page - Removed unused import
363 lines
No EOL
11 KiB
HTML
363 lines
No EOL
11 KiB
HTML
{% include "header.html" %}
|
|
<div style="float: left">
|
|
{% if pasta.content != "" %}
|
|
<button id="copy-text-button" class="small-button" style="margin-right:
|
|
0.5rem">
|
|
Copy Text
|
|
</button>
|
|
|
|
{% if args.public_path_as_str() != "" && pasta.pasta_type == "url" %}
|
|
<button id="copy-redirect-button" class="small-button" style="margin-right:
|
|
0.5rem">
|
|
Copy Redirect
|
|
</button>
|
|
{%- endif %}
|
|
<a style="margin-right: 1rem" href="{{ args.public_path_as_str() }}/raw/{{pasta.id_as_animals()}}">Raw Text
|
|
Content</a>
|
|
{%- endif %} {% if args.qr && args.public_path_as_str() != "" %}
|
|
<a style="margin-right: 1rem" href="{{ args.public_path_as_str() }}/qr/{{pasta.id_as_animals()}}">QR</a>
|
|
{%- endif %} {% if pasta.editable %}
|
|
<a style="margin-right: 1rem" href="{{ args.public_path_as_str() }}/edit/{{pasta.id_as_animals()}}">Edit</a>
|
|
{%- endif %}
|
|
<a style="margin-right: 1rem" href="{{ args.public_path_as_str() }}/remove/{{pasta.id_as_animals()}}">Remove</a>
|
|
</div>
|
|
<div style="float: right">
|
|
<a style="margin-right: 0.5rem"
|
|
href="{{ args.public_path_as_str() }}/pasta/{{pasta.id_as_animals()}}"><i>{{pasta.id_as_animals()}}</i></a>
|
|
{% if args.public_path_as_str() != "" %}
|
|
<button id="copy-url-button" class="small-button" style="margin-right: 0">
|
|
Copy URL
|
|
</button>
|
|
{%- endif %}
|
|
</div>
|
|
|
|
<br>
|
|
<br>
|
|
{% if pasta.encrypt_client && pasta.file.is_some() && !pasta.file_embeddable() %}
|
|
<span style="margin-left: auto; margin-right: auto; display: flex;
|
|
justify-content: center; align-items: center;">
|
|
<div id="decryption">
|
|
<label for="password-field" style="margin-bottom: 0.5em;">
|
|
Please enter your key to decrypt this upload. <sup> <a href="/guide#encryption">﹖</a></sup>
|
|
</label>
|
|
<input class="small-button" placeholder="Key" style="margin-right: 0.5rem" type="password" id="password-field"
|
|
autocomplete="off" />
|
|
|
|
<button class="small-button" id="decrypt-button" style="margin-right:
|
|
0.5rem">
|
|
<b>
|
|
Decrypt text
|
|
</b>
|
|
</button>
|
|
|
|
<button class="small-button" id="download-button" style="margin-right:
|
|
0.5rem">
|
|
<b>
|
|
Download {{pasta.file.as_ref().unwrap().name()}}
|
|
[{{pasta.file.as_ref().unwrap().size}}]
|
|
</b>
|
|
</button>
|
|
</div>
|
|
</span>
|
|
|
|
{%- endif %}
|
|
<br>
|
|
|
|
{% if pasta.content != "" %}
|
|
<div class="code-container">
|
|
<div style="clear: both;">
|
|
{% if pasta.extension == "auto" || pasta.encrypt_client %}
|
|
<pre><code id="code">{{pasta.content_escaped()}}</code></pre>
|
|
{% else if args.highlightsyntax %}
|
|
<pre><code id="code">{{pasta.content_syntax_highlighted()}}</code></pre>
|
|
{% else %}
|
|
<pre><code id="code">{{pasta.content_not_highlighted()}}</code></pre>
|
|
{%- endif %}
|
|
</div>
|
|
</div>
|
|
{%- endif %}
|
|
|
|
|
|
{% if pasta.file.is_some() && pasta.file.as_ref().unwrap().is_image() &&
|
|
pasta.file_embeddable() && !pasta.encrypt_client %}
|
|
<img id="embed" src="{{ args.public_path_as_str()}}/file/{{pasta.id_as_animals()}}" height="300" />
|
|
<span style="margin-left: auto; margin-right: auto; display: flex;
|
|
justify-content: center; align-items: center;">
|
|
<p style="font-size: small;">{{pasta.file.as_ref().unwrap().name()}}
|
|
[{{pasta.file.as_ref().unwrap().size}}]</p>
|
|
<a href="{{ args.public_path_as_str() }}/file/{{pasta.id_as_animals()}}" id="download-link" download>
|
|
<button class="download-button" autofocus>
|
|
Download
|
|
</button>
|
|
</a>
|
|
</span>
|
|
{%- endif %}
|
|
|
|
{% if pasta.file.is_some() && pasta.file.as_ref().unwrap().is_video() &&
|
|
pasta.file_embeddable() && !pasta.encrypt_client %}
|
|
<video id="embed" controls src="{{ args.public_path_as_str()}}/file/{{pasta.id_as_animals()}}" height="300"></video>
|
|
<span style="margin-left: auto; margin-right: auto; display: flex;
|
|
justify-content: center; align-items: center;">
|
|
<p style="font-size: small;">{{pasta.file.as_ref().unwrap().name()}}
|
|
[{{pasta.file.as_ref().unwrap().size}}]</p>
|
|
<a href="{{ args.public_path_as_str() }}/file/{{pasta.id_as_animals()}}" download id="download-link">
|
|
<button class="download-button">
|
|
Download
|
|
</button>
|
|
</a>
|
|
</span>
|
|
{%- endif %}
|
|
|
|
<div>
|
|
{% if args.show_read_stats %} {% if pasta.read_count == 1 %}
|
|
<p style="font-size: small">Read {{pasta.read_count}} time, last
|
|
{{pasta.last_read_time_ago_as_string()}}</p>
|
|
{%- else %}
|
|
<p style="font-size: small">Read {{pasta.read_count}} times, last
|
|
{{pasta.last_read_time_ago_as_string()}}</p>
|
|
{%- endif %} {%- endif %}
|
|
|
|
</div>
|
|
|
|
<br>
|
|
|
|
<script type="text/javascript" src="{{ args.public_path_as_str() }}/static/highlight/highlight.min.js"></script>
|
|
<link rel="stylesheet" href="{{ args.public_path_as_str()}}/static/highlight/highlight.min.css">
|
|
|
|
<script>
|
|
const copyURLBtn = document.getElementById("copy-url-button")
|
|
const copyTextBtn = document.getElementById("copy-text-button")
|
|
const copyRedirectBtn = document.getElementById("copy-redirect-button")
|
|
var content = `{{ pasta.content_escaped() }}`
|
|
const contentElement = document.getElementById("code");
|
|
const url = (`{{ args.short_path_as_str()}}` === "") ? `{{ args.public_path_as_str() }}/pasta/{{pasta.id_as_animals()}}` : `{{ args.short_path_as_str()}}/p/{{pasta.id_as_animals()}}`
|
|
const redirect_url = (`{{ args.short_path_as_str()}}` === "") ? `{{ args.public_path_as_str() }}/url/{{pasta.id_as_animals()}}` : `{{ args.short_path_as_str()}}/u/{{pasta.id_as_animals()}}`
|
|
|
|
const te = new TextEncoder();
|
|
|
|
// {% if pasta.extension == "auto" && !pasta.encrypt_client %}
|
|
onload = (event) => {
|
|
contentElement.innerHTML = content;
|
|
hljs.highlightAll();
|
|
contentElement.innerHTML =
|
|
wrapStringInCodeLines(contentElement.innerHTML);
|
|
};
|
|
// {% endif %}
|
|
|
|
|
|
function escapeHtml(unsafe) {
|
|
return unsafe
|
|
.replace(/&/g, "&")
|
|
.replace(/</g, "<")
|
|
.replace(/>/g, ">")
|
|
.replace(/"/g, """)
|
|
.replace(/'/g, "'");
|
|
}
|
|
|
|
function wrapStringInCodeLines(str) {
|
|
const lines = str.split(/\r?\n/); // split the string into an array of lines
|
|
const wrappedLines = lines.map((line) => `<code-line>${line}</code-line>`); // wrap each line in a "code-line" tag
|
|
return wrappedLines.join("\n"); // join the wrapped lines back into a single string with line breaks
|
|
}
|
|
|
|
const decodeEntity = (inputStr) => {
|
|
var textarea = document.createElement("textarea");
|
|
textarea.innerHTML = inputStr;
|
|
return textarea.value;
|
|
}
|
|
|
|
if (copyURLBtn) {
|
|
copyURLBtn.addEventListener("click", () => {
|
|
navigator.clipboard.writeText(url)
|
|
copyURLBtn.innerHTML = "Copied"
|
|
setTimeout(() => {
|
|
copyURLBtn.innerHTML = "Copy URL"
|
|
}, 1000)
|
|
})
|
|
}
|
|
|
|
// it will be undefined when the element does not exist on non-url pastas
|
|
if (copyRedirectBtn) {
|
|
copyRedirectBtn.addEventListener("click", () => {
|
|
navigator.clipboard.writeText(redirect_url)
|
|
copyRedirectBtn.innerHTML = "Copied"
|
|
setTimeout(() => {
|
|
copyRedirectBtn.innerHTML = "Copy Redirect"
|
|
}, 1000)
|
|
})
|
|
}
|
|
|
|
if (copyTextBtn) {
|
|
copyTextBtn.addEventListener("click", () => {
|
|
const decodeContent = decodeEntity(content)
|
|
navigator.clipboard.writeText(decodeContent)
|
|
copyTextBtn.innerHTML = "Copied"
|
|
setTimeout(() => {
|
|
copyTextBtn.innerHTML = "Copy Text"
|
|
}, 1000)
|
|
})
|
|
}
|
|
|
|
// {% if pasta.encrypt_client %}
|
|
|
|
const decryptDiv = document.getElementById('decryption');
|
|
const decryptButton = document.getElementById('decrypt-button');
|
|
const passwordField = document.getElementById("password-field");
|
|
const downloadButton = document.getElementById('download-button');
|
|
|
|
// Set up event listener for download link click
|
|
downloadButton.addEventListener('click', async (event) => {
|
|
event.preventDefault(); // prevent default click behavior
|
|
|
|
if (passwordField.value.trim() == "") {
|
|
passwordField.focus();
|
|
return false;
|
|
}
|
|
|
|
// Fetch encrypted file from server
|
|
const formData = new FormData();
|
|
|
|
// {% if pasta.encrypted_key.is_some() %}
|
|
let key = decryptWithPassword(passwordField.value.trim(), "{{ pasta.encrypted_key.as_ref().unwrap() }}");
|
|
// {%- endif %}
|
|
formData.append('password', key);
|
|
|
|
const response = await fetch('/secure_file/{{ pasta.id_as_animals() }}', {
|
|
method: 'POST',
|
|
body: formData,
|
|
})
|
|
|
|
// {% if pasta.file.is_some() %}
|
|
const encryptedFile = await response.text();
|
|
|
|
// Decrypt file contents
|
|
const decryptedContents = decryptWithPassword(passwordField.value.trim(), encryptedFile);
|
|
if (!decryptedContents) {
|
|
throw new Error('Failed to decrypt file');
|
|
}
|
|
|
|
// Create data URI for decrypted file
|
|
const dataUri = `data:text/plain;charset=utf-8,${encodeURIComponent(decryptedContents)}`;
|
|
|
|
// Create temporary anchor element
|
|
const tempAnchorEl = document.createElement('a');
|
|
tempAnchorEl.href = dataUri;
|
|
tempAnchorEl.download = '{{pasta.file.as_ref().unwrap().name()}}';
|
|
|
|
// Programmatically click anchor element to trigger download
|
|
tempAnchorEl.click();
|
|
|
|
// Remove temporary anchor element
|
|
document.re(tempAnchorEl);
|
|
// {%- endif %}
|
|
});
|
|
|
|
decryptButton.addEventListener("click", () => {
|
|
password = passwordField.value;
|
|
|
|
content = contentDecrypted = escapeHtml(decryptWithPassword(password, content));
|
|
if (contentDecrypted) {
|
|
contentElement.innerHTML = contentDecrypted;
|
|
// {% if pasta.extension == "auto" %}
|
|
hljs.highlightAll();
|
|
// {% endif %}
|
|
contentElement.innerHTML = wrapStringInCodeLines(contentElement.innerHTML);
|
|
// decryptDiv.style.display = 'none';
|
|
}
|
|
});
|
|
|
|
function decryptWithPassword(password, encryptedHex) {
|
|
const passwordBytes = aesjs.utils.utf8.toBytes(password.padStart(32, "#"));
|
|
const encryptedBytes = aesjs.utils.hex.toBytes(encryptedHex);
|
|
const aesCtr = new aesjs.ModeOfOperation.ctr(passwordBytes);
|
|
const decryptedBytes = aesCtr.decrypt(encryptedBytes);
|
|
const res = aesjs.utils.utf8.fromBytes(decryptedBytes);
|
|
if (res.endsWith("!0K")) {
|
|
return res.substring(0, res.length - "!0K".length);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
// {% endif %}
|
|
</script>
|
|
|
|
<style>
|
|
code-line {
|
|
counter-increment: line;
|
|
text-align: right;
|
|
float: left;
|
|
clear: left;
|
|
}
|
|
|
|
code-line::before {
|
|
content: counter(line);
|
|
display: inline-block;
|
|
padding-left: auto;
|
|
margin-left: auto;
|
|
text-align: left;
|
|
width: 1.8rem;
|
|
border-right: 1px solid lightgrey;
|
|
color: grey;
|
|
margin-right: 0.4rem;
|
|
-webkit-user-select: none;
|
|
-moz-user-select: none;
|
|
-ms-user-select: none;
|
|
user-select: none;
|
|
}
|
|
|
|
#code {
|
|
min-height: 2rem;
|
|
}
|
|
|
|
#embed {
|
|
background-color: #f7f7f7;
|
|
border-radius: 6px;
|
|
margin-top: 1rem;
|
|
margin-bottom: 1rem;
|
|
width: fit-content;
|
|
margin-left: auto;
|
|
margin-right: auto;
|
|
max-height: 480px;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.download-button {
|
|
margin-left: 1rem;
|
|
font-size: small;
|
|
padding: 4px;
|
|
padding-left: 0.8rem;
|
|
padding-right: 0.8rem;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.code-container {
|
|
position: relative;
|
|
}
|
|
|
|
.hidden {
|
|
display: none;
|
|
}
|
|
|
|
.small-button {
|
|
font-size: small;
|
|
padding: 4px;
|
|
padding-left: 0.8rem;
|
|
padding-right: 0.8rem;
|
|
cursor: pointer;
|
|
}
|
|
</style>
|
|
|
|
{% if !args.pure_html %}
|
|
<style>
|
|
#decryption {
|
|
background-color: #f7f7f7;
|
|
border-radius: 6px;
|
|
padding: 10px;
|
|
width: fit-content;
|
|
}
|
|
</style>
|
|
{% endif %}
|
|
|
|
{% include "footer.html" %} |