F diff --git a/css/style.css b/css/style.css
--- a/css/style.css
+++ b/css/style.css
body {
background: #f0f0f0;
color: black;
- font-family: Roboto, sans-serif;
+ font-family: sans-serif;
overflow: hidden;
}
}
form {
- background: #fbfbfb;
+ background: white;
margin: 4.5rem;
padding-top: 0;
box-shadow: 0 0.8rem 1.3rem rgba(0,0,0,0.2);
border-radius: 0.5rem;
+ border-radius: 0.5rem;
border: 1px solid #b9b9b9;
}
min-width: 300px;
}
- button,
- input:not([type=file])
- {
+ input:not([type=file]) {
border: 1px solid #bbb;
- padding: 0.5rem 0.8rem;
+ padding: 0.8rem 2rem 0.5rem 2rem;
font-size: inherit;
font-family: inherit;
border-radius: 0.3rem;
- background: #fcfcfc;
+ background: #f6f6f6;
}
input[type=button], button, input[type=submit] {
cursor: pointer;
}
+ input[type=button]:hover, button:hover, input[type=submit]:hover {
+ background: white;
+ }
input[type=submit] {
margin-top: 2rem;
outline: none;
}
-
- input:hover,
- button:hover
- {
- background: white;
+ input:focus,
+ input:hover {
+ background: white;
}
input:focus {
padding: 0;
box-shadow: 0 0.8rem 1.3rem rgba(0,0,0,0.2);
border-radius: 0.5rem;
+ border-radius: 0.5rem;
border: 1px solid #b9b9b9;
display: block;
padding: 1rem;
display: grid;
- grid-gap: 0rem;
+ grid-gap: 20px;
grid-auto-rows: 10rem;
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
}
border-color: #ddd;
}
- .file > img {
- flex: 1 0 0;
- }
-
.file:hover > img {
- filter: brightness(120%);
- }
-
- .filesystem > h2 {
- display: flex;
- align-items: stretch;
- font-weight: normal;
- padding: 0rem;
- border-bottom: 1px solid #bbb;
-
- }
-
- .filesystem > h2 button {
- border: none;
- padding: 0.3rem 1.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;
+ filter: brightness(150%);
}
.path {
- display: flex;
- align-items: stretch;
- font-size: 0.8em;
+ font-size: 1.5rem;
}
- .path > .separator {
- user-select: none;
- -webkit-user-select: none;
- -ms-user-select: none;
- padding: 0 0.2rem;
- align-self: center;
+ .path > a {
+ color: #333;
+ text-decoration: none;
}
- .pathentry:hover {
+ .path > a:hover {
text-decoration: underline;
}
- .context {
- background: white;
- position: absolute;
- z-index: 1000;
- list-style-type: none;
- margin: 0;
- padding: 0;
- top: 0;
- left: 0;
-
- border: 1px solid #ccc;
- box-shadow: 0 0.3rem 0.5rem rgba(0,0,0,0.2);
- }
-
- .context > li {
- padding: 0.4rem 1.5rem;
- margin: 0;
-
- user-select: none;
- -webkit-user-select: none;
- -ms-user-select: none;
- }
-
- .context > li:hover {
- background: #2e91db;
- color: white;
+ .filesystem > h2 {
+ display: flex;
+ align-items: baseline;
+ font-weight: normal;
}
F diff --git a/index.php b/index.php
--- a/index.php
+++ b/index.php
<html>
<head>
<meta charset="utf-8">
- <link rel="preconnect" href="https://fonts.gstatic.com">
- <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap" rel="stylesheet">
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
<title>shady file upload</title> <link rel="stylesheet" type="text/css" href="css/style.css">
</head>
F diff --git a/loggedin.js b/loggedin.js
--- a/loggedin.js
+++ b/loggedin.js
- var FORM_ASYNC = true;
+ var FORM_ASYNC = false;
const 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");
the_file.onchange = on_file_added;
- var pwd = [];
- const pending_uploads = [];
-
- var context_menu = null;
-
- class FileView {
- constructor(filename, visuals, mimetype, is_directory) {
- this.filename = filename;
- this.visuals = visuals;
- this.mimetype = mimetype;
- this.is_directory = is_directory;
- }
- }
+ var files = [];
- class PendingUpload {
- constructor(fileview) {
- this.fileview = fileview;
- }
- }
+ const pwd = "/";
- var files = [];
+ const pending_uploads = [];
function on_file_added(_e) {
if (the_file.files.length >= 1) {
return;
}
- var fileview = add_file_visuals(filename_input.value, false, "pending");
-
// Send the form asynchronously through the fetch api
fetch(upload_form.action, {
method: upload_form.method,
body: new FormData(upload_form)
}).then((resp) => {
if (resp.status == 200) {
- done_upload(fileview);
- } else {
+ add_file_visuals(filename_input.value, true);
+ }
+ else {
alert("Upload failed");
}
}, () => {
alert("Upload failed")
});
-
- pending_uploads.push(fileview);
+
+
}
else {
alert("No files selected");
}
- }
-
- function done_upload(fileview) {
- var index = pending_uploads.indexOf(fileview);
- if (index >= 0)
- pending_uploads.splice(index, 1);
- load_dir();
}
- function load_dir() {
-
- while (the_path.children.length > 1)
- the_path.removeChild(the_path.lastChild);
-
- for (let i = 0; i < pwd.length; i++) {
- var d = pwd[i];
-
- 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');
- entry.innerText = d;
- the_path.appendChild(entry);
-
- entry.onclick = () => {
- pwd.length = i + 1;
- load_dir();
- }
- }
-
+ function load_dir(pwd) {
var data = new FormData();
- data.append('path', get_path());
+ data.append('path', '/');
var xhr = new XMLHttpRequest();
xhr.open('POST', '/php/readdir.php', true);
xhr.onload = function () {
for (const f of files)
- f.visuals.remove();
+ f[1].remove();
files = [];
var json = JSON.parse(this.responseText);
for (const f of json) {
- add_file_visuals(f.name, f.is_directory, f.mimetype);
+ add_file_visuals(f.name, f.mimetype);
}
};
xhr.send(data);
}
- function delete_file(filename) {
- var file_full_path = get_path() + filename;
-
- var data = new FormData();
- data.append('path', file_full_path);
-
- var xhr = new XMLHttpRequest();
- xhr.open('POST', '/php/delete.php', true);
- xhr.onload = function () {
- load_dir();
- };
- xhr.send(data);
- }
-
- function rename_file(filename) {
- var file_full_path = get_path() + filename;
-
- var new_name = prompt(`Rename ${filename} to`, filename);
- if (!new_name)
- return;
-
- var data = new FormData();
- data.append('path', file_full_path);
- data.append('new_name', new_name);
-
- var xhr = new XMLHttpRequest();
- xhr.open('POST', '/php/rename.php', true);
- xhr.onload = function () {
- load_dir();
- };
- xhr.send(data);
- }
-
- function add_file_visuals(name, is_directory, mimetype) {
+ function add_file_visuals(name, mimetype) {
var fileDiv = document.createElement('div');
var img = document.createElement('img');
var filename = document.createElement('div');
- if (is_directory) {
- img.src="/mimeicons/directory.png";
- fileDiv.onclick = () => {
- pwd.push(name);
- load_dir();
- }
- } else {
- img.src=`/mimeicons/${mimetype.replace("/", "-")}.png`;
- }
-
- fileDiv.oncontextmenu = (e) => {
- context(e, [
- ['Open', () => {
- if (is_directory) {
- pwd.push(name);
- load_dir();
- } else {
- alert('not implemented');
- }
- }],
- ['Rename', () => { rename_file(name); }],
- ['Share', () => {alert('not implemented')}],
- ['Delete', () => { delete_file(name); }],
- ]);
- e.preventDefault();
- }
-
+ img.src="/mimeicons/application-pdf.png";
fileDiv.classList.add('file');
filename.classList.add('filename');
filename.innerText = name;
- if (mimetype == "pending")
- fileDiv.classList.add('pending');
-
fileDiv.appendChild(img);
fileDiv.appendChild(filename);
current_directory.appendChild(fileDiv);
- var file = new FileView(name, fileDiv, mimetype, is_directory);
- files.push(file);
- return file;
+ files.push([name, fileDiv]);
+
+ return fileDiv;
}
function begin_upload() {
the_file.click();
}
- function context(e, entries) {
- if (context_menu)
- context_menu.remove();
-
- context_menu = document.createElement('ul');
- context_menu.classList.add('context');
-
- context_menu.style.left = e.clientX + "px";
- context_menu.style.top = e.clientY + "px";
-
-
- for (const e of entries) {
- const li = document.createElement('li');
- li.innerText = e[0];
- li.onclick = e[1];
- context_menu.appendChild(li);
- }
-
- document.body.appendChild(context_menu);
- }
-
- function get_path() {
- var path = "/";
- for (const d of pwd)
- path += d + "/";
- return path;
- }
-
- document.body.onclick = () => {
- if (context_menu)
- context_menu.remove();
- }
-
- load_dir();
+ load_dir("/");
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="begin_upload()">New Folder</button>
- <div class="separator"></div>
- <div class="path" id="the_path">
- <!-- <a class="pathentry" href="#"> /</a><a class="pathentry" href="#">foo/</a><a class="pathentry" href="#">bar</a> -->
- <button class="pathentry" onclick="pwd.length = 0; load_dir();"><?php echo $_SESSION['username'] ?>'s files</button>
- </div>
+ <h2 style="display: flex; gap: 1rem;">
+ <div class="path">
+ <a class="pathentry" href="#"> <?php echo $_SESSION['username'] ?>'s files/</a><a class="pathentry" href="#">foo/</a><a class="pathentry" href="#">bar</a></div>
+ <input id="upload_btn" type="button" value="Upload" onclick="begin_upload()">
</h2>
<div class="files" id="current_directory">
<input type="file" name="the_file" id="the_file">
</form>
-
<script src="loggedin.js"></script>
F diff --git a/mimeicons/directory.png b/mimeicons/directory.png
deleted file mode 100644
B Binary files a/mimeicons/directory.png and /dev/null differ
F diff --git a/mimeicons/pending.png b/mimeicons/pending.png
deleted file mode 100644
B Binary files a/mimeicons/pending.png and /dev/null differ
F diff --git a/mimeicons/text-plain.png b/mimeicons/text-plain.png
deleted file mode 100644
B Binary files a/mimeicons/text-plain.png and /dev/null differ
F diff --git a/php/database.php b/php/database.php
--- a/php/database.php
+++ b/php/database.php
{
$ret=new User;
- $prep=$this->pdo->prepare("select user_id,username,email,password from users where username=:username");
+ $prep=$this->pdo->prepare("select user_id,username,email,password,home_directory from users where username=:username");
$prep->bindParam(':username',$user);
$prep->execute();
$ret->user_id=$hold["user_id"];
$ret->username=$hold["username"];
$ret->email_address=$hold["email"];
+ $ret->home_directory=$hold["home_directory"];
return $ret;
}else
{
$ret=$statement->execute(PDO::FETCH_ASSOC);
return $ret["home_directory"];
}
- function get_node_id($name,$directory_id)
+
+
+ /*returns assoc array*/
+ function get_nodes_with_name($name)
{
- $hold=NULL;
- $statement=NULL;
- $ret=[];
- if($name != NULL)
+ $statement=$this->pdo->prepare(
+ "select node_id
+ from node_links
+ where name=:name"
+ );
+ $statement->bindParam(':name',$name);
+ if($statement->execute()==NULL)
{
- if($directory_id!=NULL)
- {
- $statement=$this->pdo->prepare(
- "select nl.node_id as id from node_links nl
- inner join nodes n on n.node_id=nl.node_id
- where name=:name and directory_id=:directory_id)");
- $statement->bindParam(':name',$name);
- $statement->bindParam(':directory_id',$directory_id);
- }else
- {
- /*get all node_ids with the name name*/
- $statement=$this->pdo->prepare("select node_id as id from nodes where name=:name");
- $statement->bindParam(':name',$name);
- }
- if($statement==NULL)
- {
- error_log("statement is null");
- exit(1);
- }
- }else {
- $statement=$this->pdo->prepare("select node_id as id from node_links where directory_id=:dir_id");
- $statement->bindParam(':dir_id',$directory_id);
+ error_log("there was a problem with the sql statement at get_nodes_with_name");
+ return [];
+ }
+ return $statement->fetchAll(PDO::FETCH_ASSOC);
+ }
+
+ /*returns assoc array*/
+ function get_node_with_code($code)
+ {
+ $statement=$this->pdo->prepare(
+ "select node_id as id
+ from nodes
+ where code=:code"
+ );
+ $statement->bindParam(':code',$code);
+ if($statement->execute()==NULL)
+ {
+ error_log("there was a problem with the sql statement at get_nodes_with_code");
+ return [];
}
+ return $statement->fetchAll(PDO::FETCH_ASSOC);
+ }
+ /* I think this only makes sense if node is a dir*/
+ /* returns assoc array of nodes*/
+ function get_links_of(int $node_id)
+ {
+ $statement=$this->pdo->prepare("
+ select node_links.node_id as id,
+ node_links.name as name,
+ node_links.note as note,
+ nodes.is_directory as is_directory,
+ nodes.code as code
+ from node_links
+ inner join nodes on
+ nodes.node_id=node_links.node_id
+ where nodes.node_id=:id
+ ");
+ $statement->bindParam(':id',$node_id);
+ if($statement->execute()==false)
+ {
+ error_log("there is an error in the sql statement in get_links_of");
+ return [];
+ }
+ return $statement->fetchAll(PDO::FETCH_ASSOC);
+ }
+
+ /*if both are not null returns the id of the node with the name name in the directory_id node*/
+ function get_node_id($name,$directory_id)
+ {
+ $statement=$this->pdo->prepare(
+ "select nl.node_id as id from node_links nl
+ inner join nodes n on n.node_id=nl.node_id
+ where name=:name and directory_id=:directory_id)");
+ $statement->bindParam(':name',$name);
+ $statement->bindParam(':directory_id',$directory_id);
if($statement->execute()==false)
{
error_log("there is an error in the sql statement in get_node_id");
- exit(1);
+ return NULL;
}
-
- while($hold=$statement->fetch(PDO::FETCH_ASSOC))
+ $hold=$statement->fetch(PDO::FETCH_ASSOC);
+ if($hold==false)
+ {
+ return NULL;
+ }else
{
- print_r($hold);
- array_push($ret,$hold["id"]);
+ return $hold["id"];
}
- return $ret;
}
+
+
+
+
+
+ /*is used to get a random codename for the node as well*/
function get_random_node_name(string $prefix)
{
do{
$proposal=uniqid($prefix,true);
- }while($this->get_node_id($proposal,NULL)!=NULL);
+ }while(count($this->get_nodes_with_name($proposal))!=0);
return $proposal;
}
- /*returns NULL if node doesn't exist*/
- /*if name is NULL return all node ids in the directory*/
- /*if directory is NULL return all node ids with the name name*/
- /*if both are null return NULL*/
- /*returns node id*/
+
+
+
+
+
+ /*this is used to create seperate roots for the users*/
function create_dangling_directory(): int
{
- $dir_name=$this->get_random_node_name("");
+ $code_name=$this->get_random_node_name("");
global $storage_root;
- $prep=$this->pdo->prepare("insert into nodes(is_directory,relative_path,name) values(true,:root,:name)");
- $prep->bindParam(':name',$dir_name);
+ $prep=$this->pdo->prepare("insert into nodes(is_directory,relative_path,code) values(true,:root,:code)");
+ $prep->bindParam(':code',$code_name);
$prep->bindParam(':root',$storage_root);
if($prep->execute()==false)
{
exit(1);
}
- $id=$this->get_node_id($dir_name,NULL);
+ $id=$this->get_node_with_code($code_name);
if(count($id)!=1)
{
error_log("created a dangling directory but couldn't find it afterward. Fatal error!");
}
//print count($id);
- return $id[0];
+ return $id[0]["id"];
+ }
+
+ /*links source to target*/
+ function link_nodes(int $target_id,int $source_id,string $name,string $note)
+ {
+ $statement=$this->pdo->prepare("
+ insert into
+
+ ");
}
- /*returns the file name as it must be in the filesystem*/
- function create_file_node(string $filename): string
+ /*returns the file name as it must be in the filesystem relative to the storage root*/
+ function create_file_node(string $filename,int $dir_id): string
{
global $storage_root;
+ /*checkout the directory*/
+ $dir_prep=$this->pdo->prepare("
+ select
+ nodes.is_directory as is_directory,
+ node_access.can_edit as can_edit
+ from nodes
+ inner join node_access on
+ nodes.node_id=node_access.node_id
+ where nodes.node_id=:dir_id
+ ");
+ if($dir_prep->execute()==false)
+ {
+ error_log("could not exedude dir sql statement in create_file_node");
+ return "error";
+ }
+ $dir=$dir_prep->fetch(PDO::FETCH_ASSOC);
+ if($dir["is_directory"]==false)
+ {
+ return "error";
+ }
+ if($dir["can_edit"]==false)
+ {
+ /*TODO*/
+ return "error";
+ }
+
+ /*generate the node*/
$code=$this->get_random_node_name("");
if($filename==NULL)return "error";
- $prep=$this->pdo->prepare("insert into nodes(is_directory,relative_path,name,code)
- values(false,:root,:name,:code)
+ $prep=$this->pdo->prepare("insert into nodes(is_directory,relative_path,code)
+ values(false,:root,:code)
");
- $prep->bindParam(':name',$filename);
$prep->bindParam(':root',$storage_root);
$prep->bindParam(':code',$code);
/*not so quiet error*/
return "error";
}
+ /*link the node to the directory*/
return $code;
}
+ /*checks if there is a link between two node_id-s*/
function are_linked(int $directory_id,int $node_id): bool
{
$prepare=$this->pdo->prepare("select node_id
F diff --git a/php/login.php b/php/login.php
--- a/php/login.php
+++ b/php/login.php
}
$_SESSION['username'] = $user->username;
+ $_SESSION['user_object'] = $user;
+
header('Location: /');
?>
F diff --git a/php/node.php b/php/node.php
--- a/php/node.php
+++ b/php/node.php
<?php
require_once "database.php";
+ require_once "user.php";
- class Node
+
+ /*returns an assoc arrat of Node-s*/
+ /*path is in terms of the simulated filesystem*/
+ function get_directory(string $abstract_path,User $user)
{
- public $node_id;
- public $is_directory;
- public $relative_path;
- public $type;
- public $name;
- public $note;
- function __construct($node_id)
+ if($abstract_path[0]!="/")
{
- $this->node_id=$node_id;
+ return NULL;
}
- }
-
- class Current_Directory extends Node
- {
- /*an array of the dir_ids taken to reach here*/
- public $path;
-
- function __construct($user_id)
+ if($component=strtok($abstract_path,"/")==false)
{
- $this->dir_id=get_home_id($user_id);
- $this->path=[$dir_id];
+ return NULL;
}
- function change_directory($directory_id):bool
+ $current_dir=$database->get_node($component,$user->home_directory);
+ if($current_dir==NULL)
+ return NULL;
+ /*traverse path*/
+ while($component=strtok("/"))
{
- global $database;
- if(!$database->is_directory($directory_id))
- {
- return false;
- }
-
+ $current_dir=get_node($component,$current_dir);
+ if($current_dir==NULL)
+ return NULL;
}
+ return get_links_of(NULL,$current_dir);
}
?>
F diff --git a/php/upload.php b/php/upload.php
--- a/php/upload.php
+++ b/php/upload.php
require_once "database.php";
require_once "configuration.php";
+ echo 1;
if (!isset( $_POST["filename"]) || !isset($_FILES["the_file"]))
{
- http_response_code(400);
error_log("someone tried to upload something impropperly");
+ http_response_code(400);
exit(1);
}
+ echo 2;
- $file = $_FILES["the_file"];
- $filename= $_POST["filename"];
+ $file=$_FILES["the_file"];
+ $filename=$_POST["filename"];
+ echo 3;
$codename=$database->create_file_node($filename);
+ echo $codename;
if($codename=="error")
{
+ error_log("could not create file_node in upload.php");
http_response_code(400);
exit(0);
}
F diff --git a/php/user.php b/php/user.php
--- a/php/user.php
+++ b/php/user.php
public $user_id;
public $username;
public $email_address;
- public $current_directory;
+ public $home_directory;
}
?>
F diff --git a/sql/fileshare.sql b/sql/fileshare.sql
--- a/sql/fileshare.sql
+++ b/sql/fileshare.sql
is_directory boolean default false,
relative_path varchar(500) not null,
type varchar(20) not null default 'data',
- note varchar(200) not null default "",
code varchar(100) not null default "error",
primary key (node_id)
);
directory_id int not null,
node_id int not null,
name varchar(100) not null default 'no name',
+ note varchar(200) not null default "",
check (directory_id != node_id),
foreign key (directory_id) references nodes(node_id),
foreign key (node_id) references nodes(node_id)