F diff --git a/css/style.css b/css/style.css --- a/css/style.css +++ b/css/style.cssdisplay: flex;flex: 1 0 0;align-items: stretch;++ user-select: none;+ -webkit-user-select: none;+ -ms-user-select: none;}#page > * {justify-content: center;}- .filesystem > h2,form > h2 {color: #4d4d4d;margin: 0;border-top-right-radius: 0.5rem;}++ .window h3 button,+ .window > h2 button+ {+ border: none;+ padding: 0.3rem 1rem;+ background: inherit;+ border-radius: 0;+ }++ .window h3 button:not(.pathentry):hover {+ background: white;+ }++ .window h3 > .separator {+ flex: 0 0 1px;+ align-self: stretch;+ background: #bbb;+ }++ .window > h2 > *:first-child {+ border-top-left-radius: 0.5rem;+ }form p {margin: 1rem 0px 0.3rem 0px;}-.hero_form_error {animation: fadein 0.2s;background-color: #ff4d4d;display: none;}- .filesystem {- background: #fafafa;- margin: 1rem;+ .window {+ margin: 0rem;padding: 0;box-shadow: 0 0.8rem 1.3rem rgba(0,0,0,0.2);border-radius: 0.5rem;border: 1px solid #b9b9b9;display: block;+ position: absolute;+ top: 0;+ left: 0;+ width: 800px;+ height: 600px;++ transition: opacity 0.3s;+ display: flex;+ flex-direction: column;+ }++ .foldercontents, .filecontents {+ background: rgba(250, 250, 250, .8);+ flex: 1 0 0;+ }++ .filecontents {+ padding: 0.8rem;+ font-size: 1.1rem;+ }++ .window h3,+ .window > h2 {+ color: #4d4d4d;+ background: #f0f0f0;+ margin: 0;+++ display: flex;+ align-items: stretch;+ font-weight: normal;+ padding: 0rem;+ border-bottom: 1px solid #bbb;+ }++ .window > h2 {+ font-size: 1.3rem;+ border-top-left-radius: 0.5rem;+ border-top-right-radius: 0.5rem;+ cursor: grab;+ }++ .window h3 {+ font-size: 1.2rem;+ }++ .window.dragged {+ /* opacity: 0.9; */}.files {display: flex;flex-direction: column;align-items: center;- border: 1px solid #fafafa;+ border: 1px solid rgba(0,0,0,0);border-radius: 0.1rem;}}.file:hover:not(.dragged) {- background: white;+ background: rgba(255,255,255, 0.5);color: black;border-color: #ddd;}filter: brightness(120%);}- .filesystem > h2 {- display: flex;- align-items: stretch;- font-weight: normal;- padding: 0rem;- border-bottom: 1px solid #bbb;- font-size: 1.3rem;- }-- .filesystem > h2 button {- border: none;- padding: 0.3rem 1rem;- background: inherit;- border-radius: 0;- }-- .filesystem > h2 button:not(.pathentry):hover {- background: white;- }-- .filesystem > h2 > .separator {- flex: 0 0 1px;- align-self: stretch;- background: #bbb;- }-- .filesystem > h2 > *:first-child {- border-top-left-radius: 0.5rem;- }-.path {display: flex;align-items: stretch;- font-size: 0.8em;}.path > .separator {background: #2e91db;color: white;}++ .backdrop {+ position: absolute;+ width: 100%;+ height: 100%;++ user-select: none;+ -webkit-user-select: none;+ -ms-user-select: none;+ background-image: url("/img/backdrop.jpg");+ background-size: cover;+ }F diff --git a/img/backdrop.jpg b/img/backdrop.jpg new file mode 100644B Binary files /dev/null and b/img/backdrop.jpg differF diff --git a/loggedin.js b/loggedin.js --- a/loggedin.js +++ b/loggedin.jsconst upload_form = document.getElementById("upload_form");const the_file = document.getElementById("the_file");const filename_input = document.getElementById("filename");- const upload_btn = document.getElementById("upload_btn");- const the_path = document.getElementById("the_path");- const current_directory = document.getElementById("current_directory");+ const current_directory = document.getElementById("current_directory");const upload_parent_directory = document.getElementById("upload_parent_directory");the_file.onchange = on_file_added;- var pwd = [];+ var windows = [];+ var focus = null;var context_menu = null;var dragging = null;body: new FormData(upload_form)}).then((resp) => {if (resp.status == 200) {- load_dir();+ openfile(true);} else {alert("Upload failed");}}}- function load_dir() {- while (the_path.children.length > 1)+ function update_path_visuals() {+ var the_path = focus.visuals.getElementsByClassName('path')[0];++ while (the_path.children.length > 0)the_path.removeChild(the_path.lastChild);- for (let i = 0; i < pwd.length; i++) {- var d = pwd[i];+ for (let i = -1; i < focus.pwd.length; i++) {+ var d;+ if (i >= 0) {+ d = focus.pwd[i];+ var separator_div = document.createElement('div');+ separator_div.classList.add('separator');+ the_path.appendChild(separator_div);+ separator_div.innerText = "»";+ }+ else+ d = "Root";- var separator_div = document.createElement('div');- separator_div.classList.add('separator');- the_path.appendChild(separator_div);- separator_div.innerText = "»";var entry = document.createElement('button');entry.classList.add('pathentry');add_link_functionality(entry, i + 1);}+ }++ function openfile_nondir() {+ var data = new FormData();+ data.append('folder', get_path(focus.pwd.length - 1));+ data.append('filename', focus.pwd[focus.pwd.length - 1]);++ var xhr = new XMLHttpRequest();++ focus.pwd.push();++ update_path_visuals();++ xhr.open('POST', '/php/readfile.php', true);++ focus.filecontents.innerText = "Loading...";+ focus.filecontents.style.display = 'block';+ focus.foldercontents.style.display = 'none';++ xhr.onload = function () {+ focus.filecontents.innerText = xhr.responseText;+ };+ xhr.send(data);+ }++ function opendir() {++ update_path_visuals();var data = new FormData();data.append('path', get_path());};xhr.send(data);++ focus.filecontents.style.display = 'none';+ focus.foldercontents.style.display = 'block';+ }++ function openfile(is_directory) {+ if (is_directory) {+ opendir();+ } else {+ openfile_nondir();+ }}function delete_file(filename) {var xhr = new XMLHttpRequest();xhr.open('POST', '/php/delete.php', true);xhr.onload = function () {- load_dir();+ openfile(true);};xhr.send(data);}var xhr = new XMLHttpRequest();xhr.open('POST', '/php/rename.php', true);xhr.onload = function () {- load_dir();+ openfile(true);};xhr.send(data);}var xhr = new XMLHttpRequest();xhr.open('POST', '/php/move.php', true);xhr.onload = function () {- load_dir();+ openfile(true);};xhr.send(data);}- function new_folder() {- var dirname = prompt(`Directory name`, "New Folder");+ function new_folder() { var dirname = prompt(`Directory name`, "New Folder");if (!dirname)return;var xhr = new XMLHttpRequest();xhr.open('POST', '/php/mkdir.php', true);xhr.onload = function () {- load_dir();+ openfile(true);};xhr.send(data);}- function begin_drag(e, fileview) {+ function begin_drag_fileview(e, fileview) {if (dragging)end_drag();dragging_placeholder = document.createElement('div');- fileview.visuals.parentNode.insertBefore(dragging_placeholder, fileview.visuals);+ dragging_fileview = fileview;dragging = fileview.visuals;- dragging_fileview = fileview;++ // document.body.appendChild(dragging);++ begin_drag(e, fileview.visuals,);+ }++ function begin_drag(e, obj) {++ dragging = obj;dragging.classList.add("dragged");var elemRect = dragging.getBoundingClientRect();+ dragging_offset_x = e.clientX - elemRect.left;+ dragging_offset_y = -e.clientY + elemRect.top;+- dragging_offset_x = elemRect.width - (elemRect.left - e.clientX);- dragging_offset_y = elemRect.top - e.clientY;+ if (dragging_placeholder)+ obj.parentNode.insertBefore(dragging_placeholder, obj);++ dragging.style.left = (e.clientX - dragging_offset_x) + "px";+ dragging.style.top = (e.clientY + dragging_offset_y) + "px";- dragging.style.position = "absolute";dragging.style.width = elemRect.width + "px";dragging.style.height = elemRect.height + "px";- document.body.appendChild(dragging);- dragging.style.left = (e.clientX - dragging_offset_x) + "px";- dragging.style.top = (e.clientY + dragging_offset_y) + "px";+ dragging.style.position = "absolute";+ document.body.appendChild(dragging);}- function end_drag(e) {- dragging_placeholder.parentNode.insertBefore(dragging, dragging_placeholder);- dragging_placeholder.remove();- dragging.style.removeProperty("position");- dragging.style.removeProperty("width");- dragging.style.removeProperty("height");- dragging.style.removeProperty("left");- dragging.style.removeProperty("top");+ function end_drag(_e) {+ if (dragging_placeholder) {+ dragging_placeholder.parentNode.insertBefore(dragging, dragging_placeholder);+ dragging_placeholder.remove();+ dragging_placeholder = null;+ }++ if (dragging_fileview) {+ dragging.style.removeProperty("position");+ dragging.style.removeProperty("width");+ dragging.style.removeProperty("height");+ dragging.style.removeProperty("left");+ dragging.style.removeProperty("top");+ dragging_fileview = null;+ }+dragging.classList.remove("dragged");dragging = null;}function add_link_functionality(link, length) {link.onclick = () => {- pwd.length = length,- load_dir();+ focus.pwd.length = length,+ openfile(true);}link.onmouseup = (e) => {- if (dragging) {+ if (dragging && dragging_fileview) {var new_folder = get_path(length);move_file(new_folder, dragging_fileview.filename);end_drag();}}- add_link_functionality(document.getElementById("home_path_entry"), 0);+ class Window {+ constructor(pwd) {+ this.pwd = pwd;+ }+ }- function open_file(fileview) {- var data = new FormData();- data.append('folder', get_path());- data.append('filename', fileview.filename);- var xhr = new XMLHttpRequest();- xhr.open('POST', '/php/readfile.php', true);- xhr.onload = function () {- console.log(xhr.responseText);+ function make_window(pwd) {+ var wnd = new Window(pwd);+ windows.push(wnd);++ var wnd_html = document.createElement('div');+ wnd_html.classList.add('window');++ var h2 = document.createElement('h2');+ wnd_html.appendChild(h2);++ h2.onmousedown = (e) => {+ begin_drag(e, wnd_html);+ e.preventDefault();};- xhr.send(data);++ path = document.createElement('div');+ path.classList.add('path');+ h2.appendChild(path);++ wnd_html.style.width = "800px";+ wnd_html.style.height = "600px";+ wnd_html.style.position = "absolute";+ wnd_html.style.left = "300px";+ wnd_html.style.top = "300px";++ wnd.visuals = wnd_html;++ {+ wnd.foldercontents = document.createElement('div');+ wnd.foldercontents.classList.add('foldercontents');+ wnd_html.appendChild(wnd.foldercontents);++ var h3 = document.createElement('h3');+ wnd.foldercontents.appendChild(h3);++ var upload_btn = document.createElement('button');+ upload_btn.innerText = "Upload";+ upload_btn.onclick = () => { begin_upload(); }+ h3.appendChild(upload_btn);++ var separator = document.createElement('div');+ separator.classList.add('separator');+ h3.appendChild(separator);++ var new_folder_btn = document.createElement('button');+ new_folder_btn.innerText = "New Folder";+ new_folder_btn.onclick = () => { new_folder(); }+ h3.appendChild(new_folder_btn);++ separator = document.createElement('div');+ separator.classList.add('separator');+ h3.appendChild(separator);++ wnd.filegrid = document.createElement('div');+ wnd.filegrid.classList.add('files');+ wnd.foldercontents.appendChild(wnd.filegrid);+ }++ {+ wnd.filecontents = document.createElement('div');+ wnd.filecontents.classList.add('filecontents');+ wnd_html.appendChild(wnd.filecontents);+ }++ document.body.appendChild(wnd_html);+ return wnd;}+function add_file_visuals(fileview) {var visuals = document.createElement('div');fileview.visuals = visuals;var filename = document.createElement('div');if (fileview.is_directory) {- img.src="/mimeicons/directory.png";- visuals.onclick = () => {- pwd.push(fileview.filename);- load_dir();- }+ if (fileview.filename == "trash")+ img.src="/mimeicons/user-trash.png";+ else+ img.src="/mimeicons/directory.png";} else {img.src=`/mimeicons/${fileview.mimetype.replace("/", "-")}.png`;- visuals.onclick = () => {- open_file(fileview);- }+ }++ visuals.onclick = () => {+ focus.pwd.push(fileview.filename);+ openfile(fileview.is_directory);}visuals.oncontextmenu = (e) => {if (!dragging) {context(e, [['Open', () => {- if (fileview.is_directory) {- pwd.push(fileview.filename);- load_dir();- } else {- open_file(fileview);- }+ focus.pwd.push(fileview.filename);+ openfile(fileview.is_directory);}],+ ['Open in New Window', () => {alert('not implemented')}],['Rename', () => { rename_file(fileview.filename); }],['Share', () => {alert('not implemented')}],['Delete', () => { delete_file(fileview.filename); }],}visuals.ondragstart = (e) => {- begin_drag(e, fileview);+ begin_drag_fileview(e, fileview);e.preventDefault();};visuals.appendChild(img);visuals.appendChild(filename);- current_directory.appendChild(visuals);+ focus.filegrid.appendChild(visuals);}function begin_upload() {function get_path(max_length) {if (max_length == undefined) {- max_length = pwd.length;+ max_length = focus.pwd.length;}var path = "/";for (let i = 0; i < max_length; i++) {- path += pwd[i];+ path += focus.pwd[i];if (i != max_length - 1)path += "/";}}}- document.body.onmouseup = (e) => {+ document.body.onmouseup = (_e) => {if (dragging)end_drag();}context_menu.remove();}- load_dir();++ var root_window = make_window([]);+ focus = root_window;+ openfile(true);F diff --git a/loggedin.php b/loggedin.php --- a/loggedin.php +++ b/loggedin.php- <div>- <div class="filesystem">- <h2 style="display: flex; gap: 0rem;">- <button id="upload_btn" onclick="begin_upload()">Upload</button>- <div class="separator"></div>- <button id="upload_btn" onclick="new_folder()">New Folder</button>- <div class="separator"></div>- <div class="path" id="the_path">- <button class="pathentry" id="home_path_entry">- <?php- $user=$_SESSION['user_object'];- echo $user->username;- ?>- 's files</button>- </div>- </h2>- <div class="files" id="current_directory">- </div>- </div>-- </div>+ <div class="backdrop"><form id="upload_form" style="display:none;" action="php/upload.php" method="post" enctype="multipart/form-data"><input id="filename" name="filename">F diff --git a/mimeicons/user-trash-full.png b/mimeicons/user-trash-full.png new file mode 100644B Binary files /dev/null and b/mimeicons/user-trash-full.png differF diff --git a/mimeicons/user-trash.png b/mimeicons/user-trash.png new file mode 100644B Binary files /dev/null and b/mimeicons/user-trash.png differF diff --git a/php/readfile.php b/php/readfile.php --- a/php/readfile.php +++ b/php/readfile.php$dir = get_directory($folder, $user);if (!$dir) {- error_log("/php/readfile.php - invalid directory");+ error_log("/php/readfile.php - invalid directory '$folder'");http_response_code(409);exit(0);}}}if (!$file_node) {- error_log("/php/readfile.php - invalid filename");+ error_log("/php/readfile.php - invalid filename '$filename'");http_response_code(409);exit(0);}