mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2026-09-16 23:24:40 +00:00
xss fix
This commit is contained in:
@@ -1,135 +1,201 @@
|
||||
<fieldset>
|
||||
<legend>Torrent Client</legend>
|
||||
<div id="torrent-ui">
|
||||
<h3 id="connection_status">_</h3>
|
||||
<input type="file" id="torrentf" accept=".torrent" style="display:none">
|
||||
<button onclick="document.getElementById('torrentf').click()">ADd torrent</button>
|
||||
<ul id="torrents"></ul>
|
||||
</div>
|
||||
<legend>Torrent Client</legend>
|
||||
<div id="torrent-ui">
|
||||
<h3 id="connection_status">_</h3>
|
||||
<input type="file" id="torrentf" accept=".torrent" style="display: none" />
|
||||
<button onclick="document.getElementById('torrentf').click()">
|
||||
ADd torrent
|
||||
</button>
|
||||
<ul id="torrents"></ul>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div id="torrent_details_modal" style="display:none;">
|
||||
<h3 id="modal_torrent_title"></h3>
|
||||
<h4>Files:</h4>
|
||||
<ul id="modal_files_list"></ul>
|
||||
<h4>Peers (<span id="peer_count">0</span>):</h4>
|
||||
<ul id="modal_peers_list"></ul>
|
||||
<h4>Trackers (<span id="trackers_count">0</span>):</h4>
|
||||
<ul id="modal_trackers_list"></ul>
|
||||
<button onclick="closeDetailsModal()">Close</button>
|
||||
<div id="torrent_details_modal" style="display: none">
|
||||
<h3 id="modal_torrent_title"></h3>
|
||||
<h4>Files:</h4>
|
||||
<ul id="modal_files_list"></ul>
|
||||
<h4>Peers (<span id="peer_count">0</span>):</h4>
|
||||
<ul id="modal_peers_list"></ul>
|
||||
<h4>Trackers (<span id="trackers_count">0</span>):</h4>
|
||||
<ul id="modal_trackers_list"></ul>
|
||||
<button onclick="closeDetailsModal()">Close</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let currentTorrentsData = [];
|
||||
let currentTorrentsData = [];
|
||||
|
||||
setInterval(async () => {
|
||||
const statusIndicator = document.getElementById('connection_status');
|
||||
if (!window.tjs) return statusIndicator.textContent = 'STATUS: TJS_NOT_LOADED';
|
||||
setInterval(async () => {
|
||||
const statusIndicator = document.getElementById("connection_status");
|
||||
if (!window.tjs)
|
||||
return (statusIndicator.textContent = "STATUS: TJS_NOT_LOADED");
|
||||
|
||||
try {
|
||||
const r = await window.tjs.getTorrents();
|
||||
if (!r?.result?.torrents) return statusIndicator.textContent = 'STATUS: INVALID_RESPONSE';
|
||||
try {
|
||||
const r = await window.tjs.getTorrents();
|
||||
if (!r?.result?.torrents)
|
||||
return (statusIndicator.textContent = "STATUS: INVALID_RESPONSE");
|
||||
|
||||
statusIndicator.textContent = 'STATUS: Connected';
|
||||
statusIndicator.style.color = '#00ff66';
|
||||
statusIndicator.textContent = "STATUS: Connected";
|
||||
statusIndicator.style.color = "#00ff66";
|
||||
|
||||
const torrents = document.getElementById('torrents');
|
||||
currentTorrentsData = r.result.torrents;
|
||||
const torrents = document.getElementById("torrents");
|
||||
currentTorrentsData = r.result.torrents;
|
||||
|
||||
if (currentTorrentsData.length === 0) {
|
||||
torrents.textContent = '<li>No downloads</li>';
|
||||
return;
|
||||
}
|
||||
if (currentTorrentsData.length === 0) {
|
||||
torrents.textContent = "<li>No downloads</li>";
|
||||
return;
|
||||
}
|
||||
|
||||
torrents.innerHTML="";
|
||||
currentTorrentsData.map(el => {
|
||||
const percent = el.percentDone ? (el.percentDone*100).toFixed(2) : 0.0;
|
||||
const speed = window.tjs.formatBytes ? window.tjs.formatBytes(el.rateDownload) : `${el.rateDownload} B/s`;
|
||||
const speedUp = window.tjs.formatBytes ? window.tjs.formatBytes(el.rateUpload) : `${el.rateUpload} B/s`;
|
||||
const status = window.tjs.getStatusString ? window.tjs.getStatusString(el.status) : el.status;
|
||||
const totalSize = el.totalSize; // bytes
|
||||
const ETA = el.rateDownload ? (((totalSize * (1 - el.percentDone)) / el.rateDownload) / 60).toFixed(1) + " min" : "-";
|
||||
const name = el.name || '|unknown name, maybe a bad torrent|';
|
||||
//torrents.textContent =
|
||||
//return `<li>
|
||||
// <span></span>
|
||||
// <button onclick="openTorrentDetails(${el.id})">Details</button>
|
||||
// <button onclick="removeTorrent(${el.id})">✕</button>
|
||||
//</li>`;
|
||||
const li = document.createElement('li');
|
||||
const span = document.createElement('span')
|
||||
span.textContent = `${name} — ${percent}% [${status}] (⬇ ${speed} | ⬆ ${speedUp}) ---- size = ${(totalSize/1024/1024).toFixed(2)}mb; ETA: ${ETA}`
|
||||
li.appendChild(span)
|
||||
//
|
||||
const butDetails = document.createElement('button');
|
||||
butDetails.textContent = 'Details';
|
||||
butDetails.onclick = () => openTorrentDetails(el.id);
|
||||
li.appendChild(butDetails);
|
||||
//
|
||||
const butRemove = document.createElement('button');
|
||||
butRemove.textContent = '✕';
|
||||
butRemove.onclick = () => removeTorrent(el.id);
|
||||
li.appendChild(butRemove);
|
||||
torrents.appendChild(li)
|
||||
torrents.innerHTML = "";
|
||||
currentTorrentsData
|
||||
.map((el) => {
|
||||
const percent = el.percentDone
|
||||
? (el.percentDone * 100).toFixed(2)
|
||||
: 0.0;
|
||||
const speed = window.tjs.formatBytes
|
||||
? window.tjs.formatBytes(el.rateDownload)
|
||||
: `${el.rateDownload} B/s`;
|
||||
const speedUp = window.tjs.formatBytes
|
||||
? window.tjs.formatBytes(el.rateUpload)
|
||||
: `${el.rateUpload} B/s`;
|
||||
const status = window.tjs.getStatusString
|
||||
? window.tjs.getStatusString(el.status)
|
||||
: el.status;
|
||||
const totalSize = el.totalSize; // bytes
|
||||
const ETA = el.rateDownload
|
||||
? (
|
||||
(totalSize * (1 - el.percentDone)) /
|
||||
el.rateDownload /
|
||||
60
|
||||
).toFixed(1) + " min"
|
||||
: "-";
|
||||
const name = el.name || "|unknown name, maybe a bad torrent|";
|
||||
//torrents.textContent =
|
||||
//return `<li>
|
||||
// <span></span>
|
||||
// <button onclick="openTorrentDetails(${el.id})">Details</button>
|
||||
// <button onclick="removeTorrent(${el.id})">✕</button>
|
||||
//</li>`;
|
||||
const li = document.createElement("li");
|
||||
const span = document.createElement("span");
|
||||
span.textContent = `${name} — ${percent}% [${status}] (⬇ ${speed} | ⬆ ${speedUp}) ---- size = ${(totalSize / 1024 / 1024).toFixed(2)}mb; ETA: ${ETA}`;
|
||||
li.appendChild(span);
|
||||
//
|
||||
const butDetails = document.createElement("button");
|
||||
butDetails.textContent = "Details";
|
||||
butDetails.onclick = () => openTorrentDetails(el.id);
|
||||
li.appendChild(butDetails);
|
||||
//
|
||||
const butRemove = document.createElement("button");
|
||||
butRemove.textContent = "✕";
|
||||
butRemove.onclick = () => removeTorrent(el.id);
|
||||
li.appendChild(butRemove);
|
||||
torrents.appendChild(li);
|
||||
})
|
||||
.join("");
|
||||
} catch (err) {
|
||||
statusIndicator.textContent =
|
||||
"STATUS: ERROR_WITH_DATA (f12, check your console and write issue)";
|
||||
statusIndicator.style.color = "#ff3333";
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
}).join('');
|
||||
} catch (err) {
|
||||
statusIndicator.textContent = 'STATUS: ERROR_WITH_DATA (f12, check your console and write issue)';
|
||||
statusIndicator.style.color = '#ff3333';
|
||||
}
|
||||
}, 1000);
|
||||
document.getElementById("torrentf").onchange = (e) => {
|
||||
const file = e.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
document.getElementById('torrentf').onchange = (e) => {
|
||||
const file = e.target.files[0];
|
||||
if (!file) return;
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = async () => {
|
||||
const bytes = new Uint8Array(reader.result);
|
||||
let binary = '';
|
||||
for (let i = 0; i < bytes.byteLength; i++) {
|
||||
binary += String.fromCharCode(bytes[i]);
|
||||
}
|
||||
const b64 = btoa(binary);
|
||||
if (window.tjs) await window.tjs.addTorrent(b64);
|
||||
e.target.value = '';
|
||||
};
|
||||
reader.readAsArrayBuffer(file);
|
||||
const reader = new FileReader();
|
||||
reader.onload = async () => {
|
||||
const bytes = new Uint8Array(reader.result);
|
||||
let binary = "";
|
||||
for (let i = 0; i < bytes.byteLength; i++) {
|
||||
binary += String.fromCharCode(bytes[i]);
|
||||
}
|
||||
const b64 = btoa(binary);
|
||||
if (window.tjs) await window.tjs.addTorrent(b64);
|
||||
e.target.value = "";
|
||||
};
|
||||
reader.readAsArrayBuffer(file);
|
||||
};
|
||||
|
||||
window.removeTorrent = async (id) => {
|
||||
if (window.tjs) await window.tjs.removeTorrent(Number(id));
|
||||
};
|
||||
window.removeTorrent = async (id) => {
|
||||
if (window.tjs) await window.tjs.removeTorrent(Number(id));
|
||||
};
|
||||
|
||||
window.openTorrentDetails = (id) => {
|
||||
const torrent = currentTorrentsData.find(t => String(t.id) === String(id));
|
||||
if (!torrent) return;
|
||||
window.openTorrentDetails = (id) => {
|
||||
const torrent = currentTorrentsData.find(
|
||||
(t) => String(t.id) === String(id),
|
||||
);
|
||||
if (!torrent) return;
|
||||
|
||||
document.getElementById('modal_torrent_title').textContent = `DETAILS: ${torrent.name} (#${torrent.id})`;
|
||||
document.getElementById("modal_torrent_title").textContent =
|
||||
`DETAILS: ${torrent.name} (#${torrent.id})`;
|
||||
|
||||
const filesList = document.getElementById('modal_files_list');
|
||||
filesList.textContent = torrent.files?.length
|
||||
? torrent.files.map(f => `<li>${f.name} — ${(f.bytesCompleted / 1048576).toFixed(2)} / ${(f.length / 1048576).toFixed(2)} MB (${((f.bytesCompleted / f.length) * 100 || 0).toFixed(1)}%)</li>`).join('')
|
||||
: '<li>NO_FILES</li>';
|
||||
const filesList = document.getElementById("modal_files_list");
|
||||
filesList.innerHTML = "";
|
||||
|
||||
const peersList = document.getElementById('modal_peers_list');
|
||||
const trackersList = document.getElementById('modal_trackers_list');
|
||||
document.getElementById('peer_count').textContent = torrent.peers ? torrent.peers.length : 0;
|
||||
peersList.textContent = torrent.peers?.length
|
||||
? torrent.peers.map(p => `<li>${p.address} (${p.clientName || 'Unk'}) — ${(p.rateToClient/1024).toFixed(2)} KB/s — ${(p.rateToPeer/1024).toFixed(2)} KB/s</li>`).join('')
|
||||
: '<li>NO_PEERS</li>';
|
||||
if (torrent.files?.length) {
|
||||
torrent.files.forEach((f) => {
|
||||
const li = document.createElement("li");
|
||||
const completedMB = (f.bytesCompleted / 1048576).toFixed(2);
|
||||
const totalMB = (f.length / 1048576).toFixed(2);
|
||||
const percent = ((f.bytesCompleted / f.length) * 100 || 0).toFixed(1);
|
||||
|
||||
trackersList.textContent = torrent.trackers?.length
|
||||
? torrent.trackers.map(p => `<li>[id:${p.id}] announce: ${p.announce} ; tier - ${p.tier}</li>`).join('')
|
||||
: '<li>NO_TRACKERS</li>';
|
||||
li.textContent = `${f.name} — ${completedMB} / ${totalMB} MB (${percent}%)`;
|
||||
filesList.appendChild(li);
|
||||
});
|
||||
} else {
|
||||
const li = document.createElement("li");
|
||||
li.textContent = "NO_FILES";
|
||||
filesList.appendChild(li);
|
||||
}
|
||||
const peersList = document.getElementById("modal_peers_list");
|
||||
const trackersList = document.getElementById("modal_trackers_list");
|
||||
|
||||
document.getElementById('trackers_count').textContent = torrent.trackers ? torrent.trackers.length : -1;
|
||||
document.getElementById("peer_count").textContent = torrent.peers
|
||||
? torrent.peers.length
|
||||
: 0;
|
||||
|
||||
document.getElementById('torrent_details_modal').style.display = 'block';
|
||||
};
|
||||
peersList.innerHTML = "";
|
||||
if (torrent.peers?.length) {
|
||||
peersList.append(
|
||||
...torrent.peers.map((p) => {
|
||||
const li = document.createElement("li");
|
||||
const downSpeed = (p.rateToClient / 1024).toFixed(2);
|
||||
const upSpeed = (p.rateToPeer / 1024).toFixed(2);
|
||||
const client = p.clientName || "Unk";
|
||||
|
||||
window.closeDetailsModal = () => {
|
||||
document.getElementById('torrent_details_modal').style.display = 'none';
|
||||
};
|
||||
li.textContent = `${p.address} (${client}) — ${downSpeed} KB/s — ${upSpeed} KB/s`;
|
||||
return li;
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
const li = document.createElement("li");
|
||||
li.textContent = "NO_PEERS";
|
||||
peersList.appendChild(li);
|
||||
}
|
||||
|
||||
trackersList.innerHTML = "";
|
||||
if (torrent.trackers?.length) {
|
||||
trackersList.append(
|
||||
...torrent.trackers.map((p) => {
|
||||
const li = document.createElement("li");
|
||||
li.textContent = `[id:${p.id}] announce: ${p.announce} ; tier - ${p.tier}`;
|
||||
return li;
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
const li = document.createElement("li");
|
||||
li.textContent = "NO_TRACKERS";
|
||||
trackersList.appendChild(li);
|
||||
}
|
||||
|
||||
document.getElementById("trackers_count").textContent = torrent.trackers
|
||||
? torrent.trackers.length
|
||||
: -1;
|
||||
document.getElementById("torrent_details_modal").style.display = "block";
|
||||
};
|
||||
|
||||
window.closeDetailsModal = () => {
|
||||
document.getElementById("torrent_details_modal").style.display = "none";
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user