aboutsummaryrefslogtreecommitdiff
path: root/content/sbox/box-fix.js
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2022-01-24 11:27:37 +0100
committerWojtek Kosior <koszko@koszko.org>2022-01-24 11:45:04 +0100
commit9ceab6826af54f343a1f09ed0f6b2010552f8a2d (patch)
treeb359ba270a30d7830bd75fcd98bfbab8f3b9894f /content/sbox/box-fix.js
parent0567d00d3f9bcaae87113f5c7d256493d5f2e71a (diff)
downloadhydrilla-fixes-bundle-9ceab6826af54f343a1f09ed0f6b2010552f8a2d.tar.gz
hydrilla-fixes-bundle-9ceab6826af54f343a1f09ed0f6b2010552f8a2d.zip
Jacobk's and Koszko's improvements to app.box.com
Diffstat (limited to 'content/sbox/box-fix.js')
-rw-r--r--content/sbox/box-fix.js189
1 files changed, 121 insertions, 68 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 = `\
+<!DOCTYPE html>
+<html>
+ <head>
+ <style>
+ button, .button {
+ border-radius: 10px;
+ padding: 20px;
+ color: #333;
+ background-color:
+ lightgreen;
+ text-decoration: none;
+ display: inline-block;
+ }
+ button:hover, .button:hover {
+ box-shadow: -4px 8px 8px #888;
+ }
-const loadingIcon = document.createElement("h1");
-loadingIcon.innerText = "loading...";
-loadingIcon.style.display = "none";
+ .hide {
+ display: none;
+ }
-const error_msg = document.createElement("h1");
-error_msg.innerText = "error occured :(";
-error_msg.style.display = "none";
+ #download_button .unofficial, #download_button .red_note {
+ display: none;
+ }
+ #download_button.unofficial .unofficial {
+ display: inline;
+ }
+ #download_button.unofficial .red_note {
+ display: block;
+ }
+ .red_note {
+ font-size: 75%;
+ color: #c55;
+ font-style: italic;
+ text-align: center;
+ }
+ </style>
+ </head>
+ <body>
+ <h1 id="loading" class="hide">loading...</h1>
+ <h1 id="error" class="hide">error occured :(</h1>
+ <h1 id="title" class="hide"></h1>
+ <div id="single_file_section" class="hide">
+ <a id="download_button" class="button">
+ <span class="unofficial">unofficial</span> download
+ <aside class="red_note">(officially disallowed)</aside>
+ </a>
+ <aside></aside>
+ <h2>File info</h2>
+ <div id="file_info"></div>
+ </div>
+ </body>
+</html>
+`;
-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();
}