Skip to content

Instantly share code, notes, and snippets.

@Th1nhNg0
Last active August 19, 2025 08:52
Show Gist options
  • Save Th1nhNg0/12247572f3a3e8a00f6196164a975de2 to your computer and use it in GitHub Desktop.
Save Th1nhNg0/12247572f3a3e8a00f6196164a975de2 to your computer and use it in GitHub Desktop.
DIGITAL LIB UEH DOWNLOAD SCRIPT
// =============================================
// Paste this in the browser console at:
// https://digital.lib.ueh.edu.vn/
// =============================================
async function sha256(message) {
const msgUint8 = new TextEncoder().encode(message);
const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8);
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}
const params = new URLSearchParams(window.location.search);
const doc = params.get('doc');
const bitsid = params.get('bitsid');
if (!(doc && bitsid)) throw new Error("Missing 'doc' or 'bitsid' URL parameter.");
const T = doc.split("");
const downloadLink = `/dspace/pdf/${T[0]}${T[1]}/${T[2]}${T[3]}/${T[4]}${T[5]}/${bitsid}.pdf`;
// If you set window.password yourself, that takes precedence.
// Otherwise compute the site’s password scheme.
const computed = await sha256("Dlc0rp#!234" + bitsid);
const pw = (typeof window.password === 'string' && window.password.length) ? window.password : computed;
console.log('Using password:', pw === computed ? '(computed sha256)' : '(manual override)');
async function loadQpdfWasm() {
const mjs = 'https://cdn.jsdelivr.net/npm/@jspawn/qpdf-wasm/qpdf.mjs';
const wasm = 'https://cdn.jsdelivr.net/npm/@jspawn/qpdf-wasm/qpdf.wasm';
const mod = await import(mjs);
const createModule = mod.default || mod;
return createModule({ noInitialRun: true, locateFile: () => wasm });
}
async function fetchPdfBytes(url) {
const res = await fetch(url, { credentials: 'same-origin', headers: { 'Accept': 'application/pdf' } });
if (!res.ok) throw new Error(`Failed to fetch PDF (${res.status})`);
return new Uint8Array(await res.arrayBuffer());
}
async function decryptPdfBytes(encBytes, pw) {
const qpdf = await loadQpdfWasm();
const inPath = '/input.pdf';
const outPath = '/output.pdf';
qpdf.FS.writeFile(inPath, encBytes);
// Decrypt and linearize (clean rewrite).
// If the file is not encrypted, this still rewrites it neatly.
try {
qpdf.callMain([`--password=${pw}`, '--decrypt', '--linearize', inPath, outPath]);
} catch (e) {
throw new Error('QPDF failed to decrypt/linearize. Check the password and encryption state.\n' + (e?.message || e));
}
return qpdf.FS.readFile(outPath);
}
function saveBytes(bytes, filename) {
const blob = new Blob([bytes], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
setTimeout(() => URL.revokeObjectURL(url), 10_000);
}
(async () => {
try {
console.log('Fetching:', downloadLink);
const enc = await fetchPdfBytes(downloadLink);
console.log('Bytes fetched:', enc.byteLength);
console.log('Decrypting with QPDF (WASM)…');
const dec = await decryptPdfBytes(enc, pw);
console.log('Unlocked bytes:', dec.byteLength);
const outName = `${bitsid}-unlocked.pdf`;
saveBytes(dec, outName);
console.log('✅ Saved:', outName);
} catch (err) {
console.error('❌ Error:', err);
}
})();
// =============================================
// 💀 Hack the Library 💀
// Paste this in the browser console at:
// https://digital.lib.ueh.edu.vn/
// Knowledge wants to be free.
// =============================================
// Function to compute the SHA256 hash of a message.
async function sha256(message) {
// Encode the message string to a Uint8Array.
const msgUint8 = new TextEncoder().encode(message);
// Get the hash as an ArrayBuffer.
const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8);
// Convert the hash buffer to an array of bytes.
const hashArray = Array.from(new Uint8Array(hashBuffer));
// Convert each byte to a two-digit hexadecimal string and join them.
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
return hashHex;
}
// Get URL parameters from the current page.
const params = new URLSearchParams(window.location.search);
const doc = params.get('doc');
const bitsid = params.get('bitsid');
// Check if both parameters exist before proceeding.
if (doc && bitsid) {
// Construct the download link.
const T = doc.split("");
const downloadLink = `/dspace/pdf/${T[0]}${T[1]}/${T[2]}${T[3]}/${T[4]}${T[5]}/${bitsid}.pdf`;
// Compute the password.
const password = await sha256("Dlc0rp#!234" + bitsid);
console.log('PASSWORD:', password);
// Function to trigger the download.
function downloadFile(url, filename) {
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a); // Append the link to the body.
a.click(); // Programmatically click the link.
document.body.removeChild(a); // Clean up the DOM.
}
// Automatically trigger the download.
downloadFile(downloadLink, `${bitsid}.pdf`);
} else {
console.error("Missing 'doc' or 'bitsid' URL parameter.");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment