From 9ceab6826af54f343a1f09ed0f6b2010552f8a2d Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Mon, 24 Jan 2022 11:27:37 +0100 Subject: Jacobk's and Koszko's improvements to app.box.com --- content/sbox/box-fix.js | 189 +++++++++++++++++++++++++++++++----------------- content/sbox/index.json | 2 +- 2 files changed, 122 insertions(+), 69 deletions(-) diff --git a/content/sbox/box-fix.js b/content/sbox/box-fix.js index e8dd9c2..709deb8 100644 --- a/content/sbox/box-fix.js +++ b/content/sbox/box-fix.js @@ -49,14 +49,13 @@ // a soundtrack in a zip file // This is a static download, so it works without this script. // https://app.box.com/s/vysdh2u78yih3c8leetgq82il954a3g3 - // some gambling add + // some gambling ad // pptx // https://app.box.com/s/nnlplkmjhimau404qohh9my10pwmo8es // a list of books(?) // txt // https://ucla.app.box.com/s/mv32q624ojihohzh8d0mhhj0b3xluzbz // "COVID-19 Pivot Plan Decision Matrix" - // cannot be downloaded (403 Forbidden): "This user is not allowed to use direct links. Please email "[support address, changes depending on where you are logged in]" for support" // If you load the proprietary scripts on this page, you'll see that there is no download button // TODO: find a public folder link (the private links I have seem to work) // TODO: find a (preferably public) link with a folder inside a folder, as these may need to be handled differently @@ -87,28 +86,90 @@ for (const script of document.scripts) { postStreamData = JSON.parse(match[1]); } -// empty the initial document body -[...document.body.childNodes].forEach(n => n.remove()); +// get domain from URL +const domain = document.location.href.split("/")[2]; -// create div container -const divContainer = document.createElement("div"); -document.body.append(divContainer); +/* Replace current page contents. */ +const replacement_html = `\ + + + + + + +

loading...

+

error occured :(

+

+
+ + unofficial download + + + +

File info

+
+
+ + +`; -divContainer.append(loadingIcon, error_msg); +/* + * We could instead use document.write(), but browser's debugging tools would + * not see the new page contents. + */ +const parser = new DOMParser(); +const alt_doc = parser.parseFromString(replacement_html, "text/html"); +document.documentElement.replaceWith(alt_doc.documentElement); -// get domain from URL -const domain = document.location.href.split("/")[2]; +const nodes = {}; +document.querySelectorAll('[id]').forEach(node => nodes[node.id] = node); + +function show_error() { + nodes.loading.classList.add("hide"); + nodes.error.classList.remove("hide"); +} + +function show_title(text) { + nodes.title.innerText = text; + nodes.loading.classList.add("hide"); + nodes.title.classList.remove("hide"); +} async function hack_file() { - loadingIcon.style.display = "initial"; + nodes.loading.classList.remove("hide"); const tokens_url = "/app-api/enduserapp/elements/tokens"; const file_nr = postStreamData["/app-api/enduserapp/shared-item"].itemID; @@ -140,7 +201,12 @@ async function hack_file() { const fields = [ "permissions", "shared_link", "sha1", "file_version", "name", "size", "extension", "representations", "watermark_info", - "authenticated_download_url", "is_download_available" + "authenticated_download_url", "is_download_available", + "content_created_at", "content_modified_at", "created_at", "created_by", + "modified_at", "modified_by", "owned_by", "description", + "metadata.global.boxSkillsCards", "expires_at", "version_limit", + "version_number", "is_externally_owned", "restored_from", + "uploader_display_name" ]; const file_info_url = @@ -181,23 +247,13 @@ async function hack_file() { `${file_info.authenticated_download_url}?${params.toString()}`; console.log("download_url", download_url); - const downloadButton = document.createElement("a"); - downloadButton.innerText = "download"; - downloadButton.href = download_url; - downloadButton.setAttribute("style", "border-radius: 10px; padding: 20px; color: #333; background-color: lightgreen; text-decoration: none; box-shadow: -4px 8px 8px #888; display: inline-block;"); - - const file_info_header = document.createElement("h2"); - file_info_header.innerText = "File info"; + show_title(file_info.name); - divContainer.append(downloadButton, file_info_header, - JSON.stringify(file_info)); - - loadingIcon.style.display = "none"; -} - -function show_error() { - loadingIcon.style.display = "none"; - error_msg.style.display = "initial"; + nodes.download_button.href = download_url; + if (!file_info.permissions.can_download) + nodes.download_button.classList.add("unofficial"); + nodes.file_info.innerText = JSON.stringify(file_info); + nodes.single_file_section.classList.remove("hide"); } if (postStreamData["/app-api/enduserapp/shared-item"].itemType == "file") { @@ -207,39 +263,36 @@ if (postStreamData["/app-api/enduserapp/shared-item"].itemType == "file") { */ hack_file().then(() => {}, show_error); } else if (postStreamData["/app-api/enduserapp/shared-item"].itemType == "folder") { - const folderHeader = document.createElement("h1"); - folderHeader.innerText = postStreamData["/app-api/enduserapp/shared-folder"].currentFolderName; - divContainer.appendChild(folderHeader); - //console.log(postStreamData["/app-api/enduserapp/shared-folder"]); - postStreamData["/app-api/enduserapp/shared-folder"].items.forEach(function(element) { - console.log(element); - const folderButton = document.createElement("a"); - folderButton.setAttribute("style", "border-radius: 10px; padding: 20px; color: #333; background-color: lightgreen; text-decoration: none; box-shadow: -4px 8px 8px #888; display: inline-block;"); // from https://api-demo.hachette-hydrilla.org/content/sgoogle_sheets_download/google_sheets_download.js - if (element.type == "file") { - folderButton.innerText = "loading..."; - // craft request - var downloadLinkGet = new XMLHttpRequest(); - downloadLinkGet.open("POST", "https://"+domain+"/index.php?rm=box_download_shared_file&shared_name="+postStreamData["/app-api/enduserapp/shared-item"].sharedName+"&file_id="+element.typedID); - downloadLinkGet.setRequestHeader("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0"); // Would this be set automatically otherwise? - downloadLinkGet.setRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"); - downloadLinkGet.setRequestHeader("Accept-Language", "en-US,en;q=0.5"); // TODO: find a test case in another language - downloadLinkGet.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); - downloadLinkGet.setRequestHeader("Upgrade-Insecure-Requests", "1"); - downloadLinkGet.onreadystatechange = function() { - if (downloadLinkGet.readyState === 4) { - //console.log(downloadLinkGet.status); - // configure download button and add it - folderButton.setAttribute("href", downloadLinkGet.responseURL); - folderButton.innerText = element.name; // show the name of the file - } - }; - downloadLinkGet.send("request_token="+config.requestToken); - } else { - folderButton.innerText = "[folders inside folders not yet supported]"; - } - divContainer.appendChild(folderButton); - }) + show_title(postStreamData["/app-api/enduserapp/shared-folder"].currentFolderName); + + // TODO: implement a download folder button (included in proprietary app) + /* + The original download folder button sends a GET request that gets 2 URLs + in the response. 1 of those URLs downloads the file, and a POST request + is sent after (or maybe while in some cases?) a file is downloaded, to + let the server know how much is downloaded. + */ + // for each item in the folder, show a button with a link to download it + postStreamData["/app-api/enduserapp/shared-folder"].items.forEach(function(item) { + console.log("item", item); + + const file_direct_url = "https://"+domain+"/index.php?rm=box_download_shared_file&shared_name="+postStreamData["/app-api/enduserapp/shared-item"].sharedName+"&file_id="+item.typedID; + + const folderButton = nodes.download_button.cloneNode(false); + folderButton.removeAttribute("id"); + + if (item.type == "file") { + folderButton.href = file_direct_url; + folderButton.innerText = item.name; // show the name of the file + } else if (item.type == "folder") { + folderButton.innerText = "[folders inside folders not yet supported]"; + } else { + folderButton.innerText = "[this item type is not supported]"; + } + + document.body.appendChild(folderButton); + }); } else { - console.log("Error: not implemented"); - // TODO: also display an error on the page + console.log('expected "folder" or "file" as the item type (postStreamData["/app-api/enduserapp/shared-item"].itemType) but got ' + postStreamData["/app-api/enduserapp/shared-item"].itemType + ' instead; this item type is not implemented'); + show_error(); } diff --git a/content/sbox/index.json b/content/sbox/index.json index cb12f1a..d794bb8 100644 --- a/content/sbox/index.json +++ b/content/sbox/index.json @@ -1,6 +1,6 @@ { "type" : "script", "name" : "box-com-downloader", -"sha256" : "1274d2a8416b79acca117d90a3473c7affbb7d19dedc9004fffeca2f82283512", +"sha256" : "18d9d75f9a122c1cd3d92011699d0f292e97bf60b79169fa19fd240eb3043368", "location" : "box-fix.js" } -- cgit v1.2.3