aboutsummaryrefslogtreecommitdiff
path: root/content/sgoogle_drive_browse/google_drive_browse_folder.js
diff options
context:
space:
mode:
Diffstat (limited to 'content/sgoogle_drive_browse/google_drive_browse_folder.js')
-rw-r--r--content/sgoogle_drive_browse/google_drive_browse_folder.js373
1 files changed, 0 insertions, 373 deletions
diff --git a/content/sgoogle_drive_browse/google_drive_browse_folder.js b/content/sgoogle_drive_browse/google_drive_browse_folder.js
deleted file mode 100644
index 7843b15..0000000
--- a/content/sgoogle_drive_browse/google_drive_browse_folder.js
+++ /dev/null
@@ -1,373 +0,0 @@
-/**
- * Copyright 2021 Wojtek Kosior
- *
- * This program is free software; you can redistribute it
- * and/or modify it under the terms of either:
- * - the GNU General Public License as published by the Free
- * Software Foundation; either version 3 of the License, or (at
- * your option) any later version, or
- * - the "A" license: <https://koszko.org/alicense.txt>; explained
- * at: <https://koszko.org/en/articles/my-new-license.html>
- *
- * As additional permission under GNU GPL version 3 section 7, you
- * may distribute forms of that code without the copy of the GNU
- * GPL normally required by section 4, provided you include this
- * license notice and, in case of non-source distribution, a URL
- * through which recipients can access the Corresponding Source.
- * If you modify file(s) with this exception, you may extend this
- * exception to your version of the file(s), but you are not
- * obligated to do so. If you do not wish to do so, delete this
- * exception statement from your version. If you delete this
- * exception statement from all source files in the program, then
- * also delete it here.
- *
- * As a special exception to the GPL, any HTML file which merely
- * makes function calls to this code, and for that purpose
- * includes it by reference shall be deemed a separate work for
- * copyright law purposes. If you modify this code, you may extend
- * this exception to your version of the code, but you are not
- * obligated to do so. If you do not wish to do so, delete this
- * exception statement from your version.
- */
-
-/* Use with https://drive.google.com/drive/folders/*** */
-
-/* Define how to handle various mime types used by Google. */
-
-const known_mimes = {
- "application/vnd.google-apps.folder": {
- links: id => ({
- view: `https://drive.google.com/drive/folders/${id}`
- }),
- type: "folder",
- is_folder: true
- },
- "application/vnd.google-apps.shortcut": {
- links: id => ({
- view: `https://drive.google.com/drive/folders/${id}`
- }),
- type: "shortcut",
- is_folder: true
- },
- "application/vnd.google-apps.document": {
- links: id => ({
- view: `https://docs.google.com/document/d/${id}`,
- download: `https://docs.google.com/document/d/${id}/export?format=odt`,
- }),
- type: "Google text document",
- new_mime: "application/vnd.oasis.opendocument.text"
- },
- "application/vnd.google-apps.spreadsheet": {
- links: id => ({
- view: `https://docs.google.com/spreadsheets/d/${id}`,
- download: `https://docs.google.com/spreadsheets/d/${id}/export?format=ods`
- }),
- type: "Google spreadsheet",
- new_mime: "application/vnd.oasis.opendocument.spreadsheet"
- },
- "application/vnd.google-apps.presentation": {
- links: id => ({
- view: `https://docs.google.com/presentation/d/${id}`,
- download: `https://docs.google.com/presentation/d/${id}/export/pptx`
- }),
- type: "Google presentation",
- new_mime: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
- },
- "application/vnd.google-apps.drawing": {
- links: id => ({
- view: `https://docs.google.com/drawings/d/${id}`,
- download: `https://docs.google.com/drawings/d/${id}/export/jpeg`
- }),
- type: "Google drawing",
- new_mime: "image/jpeg"
- },
- "application/vnd.google-apps.script": {
- links: id => ({
- download: `https://script.google.com/feeds/download/export?format=json&id=${id}`
- }),
- type: "Google script",
- new_mime: "application/vnd.google-apps.script+json"
- },
- "application/vnd.google-apps.jam": {
- links: id => ({
- download: `https://jamboard.google.com/export?id=${id}`
- }),
- type: "Google jam",
- new_mime: "application/pdf"
- }
-};
-
-/*
- * Human-friendly names defined here will be displayed to the user instead of
- * raw mime types. Please add more here.
- */
-let mime_display_overrides = {
- "image/jpeg": "JPEG image",
- "application/octet-stream": "binary data",
- "application/pdf": "PDF document",
- "application/rar": "RAR archive",
- "application/zip": "ZIP archive"
-};
-
-let default_link_producer = id => ({
- view: `https://drive.google.com/file/d/${id}`,
- download: `https://drive.google.com/uc?export=download&id=${id}`
-});
-
-for (const [mime, display_name] of Object.entries(mime_display_overrides)) {
- known_mimes[mime] = {
- links: default_link_producer,
- type: display_name,
- new_mime: mime
- }
-}
-
-delete mime_display_overrides;
-
-function get_mime_info(mime) {
- return known_mimes[mime] || {
- links: default_link_producer,
- type: mime || "",
- new_mime: mime || "application/octet-stream"
- }
-}
-
-/* Prepare folder contents data as well as data regarding the folder itself. */
-
-const content = new Map();
-
-function add_content_item(item)
-{
- const old_item = content.get(item.id) || {};
- Object.assign(old_item, item);
- content.set(item.id, old_item);
-}
-
-const this_folder = {};
-
-function replace_string_escape(match, group)
-{
- return String.fromCharCode(`0x${group}`);
-}
-
-function try_parse(data, replace_x_escapes)
-{
- if (!data)
- return null;
-
- if (replace_x_escapes)
- data = data.replaceAll(/\\x([0-9a-f]{2})/g, replace_string_escape);
-
- try {
- return JSON.parse(data);
- } catch (e) {
- console.log(e);
- }
-
- return null;
-}
-
-function process_file_data(file_data, callback)
-{
- if (!Array.isArray(file_data) || !typeof file_data[0] === "string") {
- console.log("cannot process the following file data object:",
- file_data);
- return;
- }
-
- const result = {id: file_data[0], folders: []};
-
- if (Array.isArray(file_data[1])) {
- for (const item of file_data[1]) {
- if (typeof item === "string" && item !== this_folder.id)
- result.folders.push(item);
- }
- }
- if (typeof file_data[2] === "string")
- result.filename = file_data[2];
- if (typeof file_data[3] === "string" && file_data[3].search("/") >= 0)
- result.mime = file_data[3];
- if (typeof file_data[9] === "number")
- result.date1 = new Date(file_data[9]);
- if (typeof file_data[10] === "number")
- result.date2 = new Date(file_data[10]);
-
- callback(result);
-}
-
-/*
- * By searching for scripts with calls to AF_initDataCallback we get about 7
- * matches. All arguments to this function seem to be arrays parseable as JSON,
- * but their contents are very different and only two of those ~7 arrays
- * actually hold some data useful to us. Here we try to filter out the other
- * cases and then extract the useful data.
- */
-function process_af_init_data(data)
-{
- if (!Array.isArray(data) || !/^driveweb/.test(data[0]) ||
- !Array.isArray(data[1]))
- return;
-
- /* First useful "kind" of object we can encounter is this folder's data. */
- if (typeof data[1][0] === "string") {
- process_file_data(data[1], item => Object.assign(this_folder, item));
- return;
- }
-
- /*
- * Second "kind" of object holds data about all items in the folder.
- * Folders and Files are stored in separate lists (doesn't matter to us,
- * since we distinguish them based on mime type anyway).
- */
- for (const data_sub of data[1]) {
- if (!Array.isArray(data_sub) || !/^driveweb/.test(data_sub[0]) ||
- !Array.isArray(data_sub[1]))
- continue;
- for (const item of data_sub[1])
- process_file_data(item, add_content_item);
- }
-}
-
-/*
- * Folder items data actually exists in both of the 2 kinds of scripts we search
- * for. In case of both of the regexes below we call `process_file_data' in the
- * end. As a result we process the same file multiple time as it appears in 2
- * scripts. This is, however, a good thing, because it makes a change less
- * likely to break our fix.
- */
-
-const ivd_data_regex = /\s*window\s*\['_DRIVE_ivd'\]\s*=\s*'(\\x5b[^']+)'(.*)$/;
-const af_init_data_regex = /AF_initDataCallback\s*\(.+data\s*:\s*(\[.*\])[^\]]+$/;
-
-for (const script of document.scripts) {
- const ivd_data_match = ivd_data_regex.exec(script.textContent);
- if (ivd_data_match) {
- const ivd_data = try_parse(ivd_data_match[1], true);
- if (ivd_data && Array.isArray(ivd_data) && Array.isArray(ivd_data[0])) {
- for (const item of ivd_data[0])
- process_file_data(item, add_content_item);
- }
- }
-
- const af_init_data_match = af_init_data_regex.exec(script.textContent);
- if (af_init_data_match) {
- const af_init_data = try_parse(af_init_data_match[1], false);
- if (af_init_data)
- process_af_init_data(af_init_data);
- }
-}
-
-/* Construct our own user interface. */
-
-const body = document.createElement("body");
-const folders = document.createElement("div");
-const files = document.createElement("div");
-const folders_heading = document.createElement("h2");
-const files_heading = document.createElement("h2");
-
-folders_heading.textContent = "Folders";
-files_heading.textContent = "Files";
-
-let has_folders = false;
-let has_files = false;
-
-folders.appendChild(folders_heading);
-files.appendChild(files_heading);
-
-body.setAttribute("style", "width: 100vw; height: 100vh; overflow: scroll; color: #555; margin: 15px; -webkit-user-select: initial;");
-
-const drive_folder_regex = /application\/vnd.google-apps.(folder|shortcut)/;
-
-function add_item_to_view(item_data)
-{
- const item_div = document.createElement("div");
- const item_heading = document.createElement("h4");
-
- item_div.setAttribute("style", "border: 2px solid #999; border-radius: 8px; padding: 10px; display: inline-block; margin: 2px;");
-
- let item_heading_style = "margin: 8px 4px;";
-
- if (item_data.filename) {
- item_heading.textContent = item_data.filename;
- } else {
- item_heading.textContent = "(no name)";
- item_heading_style += " font-style:italic;";
- }
- item_heading.setAttribute("style", item_heading_style);
- item_div.appendChild(item_heading);
-
- const mime_info = get_mime_info(item_data.mime);
-
- if (mime_info.type) {
- const type_div = document.createElement("div");
- type_div.setAttribute("style", "margin-bottom: 5px;");
- type_div.textContent = mime_info.type;
-
- item_div.appendChild(type_div);
- }
-
- if (mime_info.is_folder)
- has_folders = true;
- else
- has_files = true;
-
- const links = {};
- if (item_data.id)
- Object.assign(links, mime_info.links(item_data.id));
-
- if (links.view) {
- const view_button = document.createElement("a");
- view_button.setAttribute("style", "border-radius: 5px; padding: 10px; color: #333; background-color: lightgreen; text-decoration: none; box-shadow: -4px 8px 8px #888; display: inline-block; margin: 5px;");
- view_button.textContent = "view";
- view_button.href = links.view;
-
- item_div.appendChild(view_button);
- }
-
- if (links.download) {
- const download_button = document.createElement("a");
- download_button.setAttribute("style", "border-radius: 5px; padding: 10px; color: #333; background-color: lightgreen; text-decoration: none; box-shadow: -4px 8px 8px #888; display: inline-block; margin: 5px;");
- download_button.textContent = "download";
- download_button.href = links.download;
- download_button.type = mime_info.new_mime;
-
- item_div.appendChild(download_button);
- }
-
- (mime_info.is_folder ? folders : files).appendChild(item_div);
-}
-
-for (const item of content.values())
- add_item_to_view(item);
-
-if (this_folder.filename) {
- const heading = document.createElement("h1");
- heading.textContent = this_folder.filename;
- body.appendChild(heading);
-}
-if (this_folder.folders && this_folder.folders.length > 0) {
- for (const parent_id of this_folder.folders) {
- const up_button = document.createElement("a");
- let text = "go up";
-
- up_button.setAttribute("style", "border-radius: 5px; padding: 10px; color: #333; background-color: lightgreen; text-decoration: none; box-shadow: -4px 8px 8px #888; display: inline-block; margin: 5px;");
- up_button.href = `https://drive.google.com/drive/folders/${parent_id}`;
- if (this_folder.folders.length > 1)
- text = `${text} (${parent_id})`;
- up_button.textContent = text;
-
- body.appendChild(up_button);
- }
-}
-if (has_folders)
- body.appendChild(folders);
-if (has_files)
- body.appendChild(files);
-if (!(has_files || has_folders)) {
- const no_files_message = document.createElement("h3");
- no_files_message.textContent = "No files found.";
- body.appendChild(no_files_message);
-}
-
-if (document.body.firstChild.id !== "af-error-container")
- document.documentElement.replaceChild(body, document.body);