F diff --git a/css/style.css b/css/style.css
--- a/css/style.css
+++ b/css/style.css
overflow: hidden;
}
- .noselect {
- user-select: none;
- -webkit-user-select: none;
- -ms-user-select: none;
- }
-
#page {
display: flex;
flex: 1 0 0;
}
.window {
- overflow: hidden;
- box-sizing: border-box;
margin: 0rem;
padding: 0;
box-shadow: 0 0.8rem 1.3rem rgba(0,0,0,0.2);
flex-direction: column;
}
- .window.focus {
- border-color: black;
- }
-
.foldercontents, .filecontents {
- background: rgba(250, 250, 250, .9);
+ background: rgba(250, 250, 250, .8);
flex: 1 0 0;
}
border-top-left-radius: 0.5rem;
border-top-right-radius: 0.5rem;
cursor: grab;
-
- user-select: none;
- -webkit-user-select: none;
- -ms-user-select: none;
}
.window h3 {
}
.file {
- box-sizing: border-box;
padding: 0.5rem;
cursor: pointer;
color: #333;
background-image: url("/img/backdrop.jpg");
background-size: cover;
}
-
- .share_dialog_contents {
- display: flex;
- flex-direction: column;
- background: white;
- background: rgba(255,255,255, 0.9);
- }
F diff --git a/loggedin.js b/loggedin.js
--- a/loggedin.js
+++ b/loggedin.js
var context_menu = null;
var dragging = null;
-
- var dragging_candidate = null;
- var dragging_candidate_x, dragging_candidate_y;
-
var dragging_fileview;
var dragging_placeholder = null;
var dragging_offset_x = 0, dragging_offset_y = 0;
- var depth = 20;
-
class FileView {
constructor(filename, visuals, mimetype, is_directory) {
this.filename = filename;
var d;
if (i >= 0) {
d = focus.pwd[i];
- var separator_div = mk(the_path, 'div', 'separator');
+ var separator_div = document.createElement('div');
+ separator_div.classList.add('separator');
+ the_path.appendChild(separator_div);
separator_div.innerText = "ยป";
}
else
d = "Root";
- var entry = mk(the_path, 'button', 'pathentry');
+
+ var entry = document.createElement('button');
+ entry.classList.add('pathentry');
entry.innerText = d;
+ the_path.appendChild(entry);
add_link_functionality(entry, i + 1);
}
var folder = get_path();
}
- var wnd = make_share_window(folder, filename);
- focus_window(wnd);
+ var users = prompt("Enter comma separated list of users. empty = public", "");
+ if (users === null)
+ return;
+ var password = prompt("Enter a passcode", "");
+ if (password === null)
+ return;
+
+
+ var data = new FormData();
+ data.append('folder', folder);
+ data.append('filename', filename);
+ data.append('users', users);
+ data.append('password', password);
+
+ var xhr = new XMLHttpRequest();
+ xhr.open('POST', '/php/share.php', true);
+ xhr.onload = function () {
+ }
+
+ xhr.send(data);
}
function opendir() {
if (dragging)
end_drag();
- // Inserted in place by begin_drag
dragging_placeholder = document.createElement('div');
dragging_fileview = fileview;
dragging = fileview.visuals;
- dragging.style.zIndex = 50000;
- begin_drag(e, fileview.visuals);
+ // document.body.appendChild(dragging);
+
+ begin_drag(e, fileview.visuals,);
}
- function begin_drag(e, obj, dont_set_width) {
+ function begin_drag(e, obj) {
+
dragging = obj;
- dragging_candidate = null;
dragging.classList.add("dragged");
var elemRect = dragging.getBoundingClientRect();
dragging_offset_x = e.clientX - elemRect.left;
dragging_offset_y = -e.clientY + elemRect.top;
+
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";
- if (!dont_set_width) {
- dragging.style.width = elemRect.width + "px";
- dragging.style.height = elemRect.height + "px";
- }
+ dragging.style.width = elemRect.width + "px";
+ dragging.style.height = elemRect.height + "px";
dragging.style.position = "absolute";
document.body.appendChild(dragging);
}
}
- function focus_window(wnd) {
- if (focus)
- focus.visuals.classList.remove('focus');
- focus = wnd;
- if (wnd) {
- wnd.visuals.classList.add('focus');
- wnd.visuals.style.zIndex = depth ++;
- }
- }
- function make_window_base(pwd, x, y, w, h) {
+ function make_window(pwd) {
var wnd = new Window(pwd);
windows.push(wnd);
- wnd.visuals = mk(document.body, 'div', 'window');
-
- wnd.visuals.style.width = w + "px";
- wnd.visuals.style.height = h ? (h + "px") : "unset";
- wnd.visuals.style.position = "absolute";
- wnd.visuals.style.left = x + "px";
- wnd.visuals.style.top = y + "px";
-
- wnd.h2 = mk(wnd.visuals, 'h2');
-
- wnd.visuals.onmousedown = (e) => {
- focus_window(wnd);
- }
-
- wnd.h2.onmousedown = (e) => {
- if (!dragging) {
- dragging_candidate = wnd.visuals;
- dragging_candidate_x = e.clientX;
- dragging_candidate_y = e.clientY;
- }
- };
-
- return wnd;
- }
-
- function mk(parent, type, _class) {
- var el = document.createElement(type);
- parent.appendChild(el);
- if (_class)
- el.classList.add(_class);
- return el;
- }
-
- function mkhdiv(parent) {
- var hdiv = mk(parent, 'div');
- hdiv.style.display = "flex";
- hdiv.style.alignItems = "center";
- hdiv.style.padding = "0.3rem";
- hdiv.style.gap = "0.3rem";
- return hdiv;
- }
-
- function mkcheckbox(parent, label, togglefn) {
- var hdiv = mkhdiv(parent);
-
- var write_checkbox = mk(hdiv, 'input');
- write_checkbox.type = 'checkbox';
-
- var write_checkbox_label = mk(hdiv, 'label');
- write_checkbox_label.innerText = label;
- write_checkbox_label.onclick = (e) => { write_checkbox.click(); }
- write_checkbox_label.classList.add('noselect');
-
- write_checkbox.onchange = (_e) => {
- togglefn(write_checkbox.checked);
- };
- }
-
- function make_share_window(folder, filename) {
- var wnd = make_window_base(null, 400, 400, 400, 0);
-
- wnd.h2.innerText = "Share " + filename;
- wnd.h2.style.padding = "0.2rem 0.4rem";
-
- wnd.foldercontents = mk(wnd.visuals, 'div', 'share_dialog_contents');
- wnd.foldercontents.style.padding = "0.5rem";
-
- var data = {
- write_permissions: false,
- private: false,
- has_password: false,
- password: "",
- userlist: [],
- }
-
- var userlist, add_user;
- mkcheckbox(wnd.foldercontents, "Private link", (toggled) => {
- add_user.style.display = toggled ? "block" : "none";
- userlist.style.display = toggled ? "block" : "none";
- data.private = toggled;
- });
-
- userlist = mk(wnd.foldercontents, 'div');
- userlist.style.display = "none";
- add_user = mk(wnd.foldercontents, 'button');
- add_user.innerText = "Add user";
- add_user.style.display = "none";
-
- add_user.onclick = (e) => {
- var i = mk(userlist, 'input');
- i.value = 'John Doe';
-
- let index = data.userlist.length;
- data.userlist.push(i.value);
-
- i.onchange = (e) => {
- data.userlist[index] = i.value;
- }
- }
+ var wnd_html = document.createElement('div');
+ wnd_html.classList.add('window');
- // Click the add_user to add a default user
- add_user.click();
-
- mkcheckbox(wnd.foldercontents, "Give write permissions", (toggled) => {
- data.write_permissions = toggled;
- });
-
- let password_container;
- mkcheckbox(wnd.foldercontents, "Password protected", (toggled) => {
- data.has_password = toggled;
- password_container.style.display = toggled ? "flex" : "none";
- });
-
- password_container = mkhdiv(wnd.foldercontents);
- password_container.style.display = 'none'
- var password_label = mk(password_container, 'label');
- password_label.innerText = "Password";
- var password_input = mk(password_container, 'input');
- password_input.type = 'password';
- password_input.style.flex = "1 0 0";
- password_input.onchange = (_e) => {
- data.password = password_input.value;
- };
+ var h2 = document.createElement('h2');
+ wnd_html.appendChild(h2);
- var generate_url_button = mk(wnd.foldercontents, 'button');
- generate_url_button.innerText = "Generate link";
+ //h2.onmousedown = (e) => {
+ //begin_drag(e, wnd_html);
+ // e.preventDefault();
+ //};
- generate_url_button.onclick = () => {
- console.log(data);
+ path = document.createElement('div');
+ path.classList.add('path');
+ h2.appendChild(path);
- var users = "";
- if (data.private) {
- users = data.userlist.join(',');
- }
+ wnd_html.style.width = "900px";
+ wnd_html.style.height = "600px";
+ wnd_html.style.position = "absolute";
+ wnd_html.style.left = "200px";
+ wnd_html.style.top = "100px";
- var form_data = new FormData();
- form_data.append('folder', folder);
- form_data.append('filename', filename);
- form_data.append('users', users);
- form_data.append('password', data.has_password ? data.password : "");
-
- var xhr = new XMLHttpRequest();
- xhr.open('POST', '/php/share.php', true);
- xhr.onload = function () {
- alert(xhr.response);
- }
-
- xhr.send(form_data);
- delete_window();
- }
-
- return wnd;
- }
-
- function delete_window() {
- var index = windows.indexOf(focus);
- if (index >= 0) {
- windows.splice(index, 1);
- }
- focus.visuals.parentNode.removeChild(focus.visuals);
- fous = null;
- }
-
- function make_window(pwd) {
- var wnd = make_window_base(pwd, 100, 100, 800, 600);
-
- path = mk(wnd.h2, 'div', 'path');
+ wnd.visuals = wnd_html;
{
- wnd.foldercontents = mk(wnd.visuals, 'div', 'foldercontents');
- var h3 = mk(wnd.foldercontents, 'h3');
+ 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 = mk(h3, 'button');
+ var upload_btn = document.createElement('button');
upload_btn.innerText = "Upload";
upload_btn.onclick = () => { begin_upload(); }
+ h3.appendChild(upload_btn);
- mk(h3, 'div', 'separator');
+ var separator = document.createElement('div');
+ separator.classList.add('separator');
+ h3.appendChild(separator);
- var new_folder_btn = mk(h3, 'button');
+ var new_folder_btn = document.createElement('button');
new_folder_btn.innerText = "New Folder";
new_folder_btn.onclick = () => { new_folder(); }
+ h3.appendChild(new_folder_btn);
- mk(h3, 'div', 'separator');
+ separator = document.createElement('div');
+ separator.classList.add('separator');
+ h3.appendChild(separator);
- wnd.filegrid = mk(wnd.foldercontents, 'div', 'files');
+ wnd.filegrid = document.createElement('div');
+ wnd.filegrid.classList.add('files');
+ wnd.foldercontents.appendChild(wnd.filegrid);
}
{
- wnd.filecontentsroot = mk(wnd.visuals, 'div');
- var h3 = mk(wnd.filecontentsroot, 'h3');
+ wnd.filecontentsroot = document.createElement('div');
+ wnd_html.appendChild(wnd.filecontentsroot);
+
+ var h3 = document.createElement('h3');
+ wnd.filecontentsroot.appendChild(h3);
- var download_btn = mk(h3, 'button');
+ var download_btn = document.createElement('button');
download_btn.innerText = "Download";
download_btn.onclick = () => { download_file(); }
+ h3.appendChild(download_btn);
- mk(h3, 'div', 'separator');
+ separator = document.createElement('div');
+ separator.classList.add('separator');
+ h3.appendChild(separator);
- var download_btn = mk(h3, 'button');
+ var download_btn = document.createElement('button');
download_btn.innerText = "Share";
download_btn.onclick = () => { share(true); }
-
- mk(h3, 'div', 'separator');
+ h3.appendChild(download_btn);
+
+ separator = document.createElement('div');
+ separator.classList.add('separator');
+ h3.appendChild(separator);
+
+ wnd.filecontents = document.createElement('div');
+ wnd.filecontents.classList.add('filecontents');
+ wnd.filecontentsroot.appendChild(wnd.filecontents);
- wnd.filecontents = mk(wnd.filecontentsroot, 'div', 'filecontents');
}
+ document.body.appendChild(wnd_html);
return wnd;
}
// Is the current filewview the trash folder itself
var is_trash = focus.pwd.length == 0 && fileview.filename == "trash";
- var visuals = mk(focus.filegrid, 'div');
+ var visuals = document.createElement('div');
fileview.visuals = visuals;
var img = document.createElement('img');
img.src=`/mimeicons/${fileview.mimetype.replace("/", "-")}.png`;
}
- fileview.visuals.onclick = () => {
+ visuals.onclick = () => {
focus.pwd.push(fileview.filename);
openfile(fileview.is_directory);
}
visuals.appendChild(img);
visuals.appendChild(filename);
+ focus.filegrid.appendChild(visuals);
}
function begin_upload() {
if (context_menu)
context_menu.remove();
- context_menu = mk(document.body, 'ul', 'context');
-
- context_menu.onmousedown = (e) => {
- e.stopPropagation();
- }
+ context_menu = document.createElement('ul');
+ context_menu.classList.add('context');
context_menu.style.left = e.clientX + "px";
context_menu.style.top = e.clientY + "px";
li.onclick = e[1];
context_menu.appendChild(li);
}
+
+ document.body.appendChild(context_menu);
}
function get_path(max_length) {
dragging.style.left = (e.clientX - dragging_offset_x) + "px";
dragging.style.top = (e.clientY + dragging_offset_y) + "px";
}
- else if (dragging_candidate) {
- var d = Math.abs(e.clientX - dragging_candidate_x) + Math.abs(e.clientY - dragging_candidate_y);
- if (d > 15)
- begin_drag(e, dragging_candidate, true);
- }
- }
-
- document.body.onmousedown = (_e) => {
- if (context_menu)
- context_menu.remove();
}
document.body.onmouseup = (_e) => {
- if (dragging_candidate)
- dragging_candidate = null;
if (dragging)
end_drag();
}
context_menu.remove();
}
+
var root_window = make_window([]);
- focus_window(root_window);
+ focus = root_window;
openfile(true);
F diff --git a/php/.configuration.php.swp b/php/.configuration.php.swp
deleted file mode 100644
B Binary files a/php/.configuration.php.swp and /dev/null differ
F diff --git a/php/configuration.php b/php/configuration.php
--- a/php/configuration.php
+++ b/php/configuration.php
<?php
/*should be placed outside of document root*/
- $domain_name="localhost";
+ $use_https=true;
if (file_exists("/home/alex")) {
- $database_name="alex";
- $database_username="alex";
- $database_password="lol";
- $database_location="127.0.0.1";
+ $domain_name="localhost";
+ $database_name="alex";
+ $database_username="alex";
+ $database_password="lol";
+ $database_location="127.0.0.1";
- $storage_root = "/home/alex/fileup_storage";
+ $storage_root = "/home/alex/fileup_storage";
}
else {
-
- $database_name="fileup_testing";
- $database_username="outsider";
- $database_password="parola123";
- $database_location="localhost";
- /*storage root must be in the webroot*/
- $storage_root = "/srv/apache/testing/project/files/";
+ $domain_name="testing";
+ $database_name="fileup_testing";
+ $database_username="outsider";
+ $database_password="parola123";
+ $database_location="localhost";
+ /*storage root must be in the webroot*/
+ $storage_root = "/srv/apache/testing/project/files/";
}
/*if we save deleted files just in case of an error*/
F diff --git a/php/database.php b/php/database.php
--- a/php/database.php
+++ b/php/database.php
where name=:name"
);
$statement->bindParam(':name',$name);
- if($statement->execute()==NULL)
+ if($statement->execute()==false)
{
error_log("there was a problem with the sql statement at get_nodes_with_name");
- return [];
+ return NULL;
}
return $statement->fetchAll(PDO::FETCH_ASSOC);
}
- /*returns assoc array*/
+ /*returns id*/
function get_node_with_code($code)
{
$statement=$this->pdo->prepare(
where code=:code"
);
$statement->bindParam(':code',$code);
- if($statement->execute()==NULL)
+ if($statement->execute()==false)
{
error_log("there was a problem with the sql statement at get_nodes_with_code");
- return [];
+ return NULL;
}
- return $statement->fetch(PDO::FETCH_ASSOC);
+ $ret= $statement->fetch(PDO::FETCH_ASSOC);
+ return $ret["id"];
}
/* I think this only makes sense if node is a dir*/
/* returns assoc array of nodes*/
/*give premissions*/
$id=$this->get_node_with_code($code_name);
- if(count($id)!=1)
+ if($id!=NULL)
{
error_log("created a dangling directory but couldn't find it afterward. Fatal error!");
exit(1);
}
}
+ function create_shared_node(string $password,int $node_id):bool
+ {
+ $prep=$this->pdo->prepare("insert into shared_nodes(node_id,passcode)
+ values (:id,:pass)
+ ");
+ $prep->bindParam(':id',$node_id);
+ $prep->bindParam(':pass',$password);
+ if($prep->execute()==false)
+ {
+ error_log("could not create shared node in create_shared_node");
+ return false;
+ }
+ return true;
+ }
+ function get_node(int $node_id)
+ {
+ $prep=$this->pdo->prepare("select * from nodes where node_id=:id");
+ $prep->bindParam(':id',$node_id);
+ if($prep->execute()==false)
+ {
+ error_log("sql statement at get_node failed");
+ return NULL;
+ }
+ $nod=$prep->fetch(PDO::FETCH_ASSOC);
+ $ret=new Node();
+ $ret->node_id=$nod["node_id"];
+ $ret->is_directory=$nod["is_directory"];
+ $ret->relative_path=$nod["relative_path"];
+ $ret->type=$nod["type"];
+ $ret->code=$nod["code"];
+
+ return $ret;
+
+ }
/*returns the file name as it must be in the filesystem relative to the storage root*/
function create_file_node(string $filename,string $note,int $dir_id,string $mimetype,User $user): string
{
{
error_log("could not exedude dir sql statement in create_file_node");
return "error";
- }
+ }
- $dir=$dir_prep->fetch(PDO::FETCH_ASSOC);
+ $dir=$dir_prep->fetch(PDO::FETCH_ASSOC);
if($dir == false)
{
error_log("create_file_node dir isnt a directory");
/*not so quiet error*/
return "error";
}
- $new_id=$this->get_node_with_code($code)["id"];
+ $new_id=$this->get_node_with_code($code);
/*link the node to the directory*/
$this->link_nodes($dir_id,$new_id,$filename,$note);
/*give premissions to the creator*/
F diff --git a/php/node.php b/php/node.php
--- a/php/node.php
+++ b/php/node.php
require_once "database.php";
require_once "user.php";
+ class Node
+ {
+ public $node_id;
+ public $is_directory;
+ public $relative_path;
+ public $type;
+ public $code;
+ }
/*path is in terms of the simulated filesystem*/
+ /*returns NULL on error*/
function get_directory(string $abstract_path,User $user)
{
$parent_dir_id=get_directory($abstract_path,$user);
$database->unlink_nodes($parent_dir_id,$filename);
}
+ function create_share_link(string $abstract_path,string $filename,string $password,User $user,bool $can_read,bool $can_write)
+ {
+ global $database;
+ global $domain_name;
+ global $use_https;
+
+ $dir_id=get_directory($abstract_path,$user);
+ if($dir_id==NULL)
+ {
+ return NULL;
+ }
+ $node_id=get_node_id($filename,$dir_id);
+ if($node_id==NULL)
+ {
+ return NULL;
+ }
+ if($database->create_shared_node($password,$node_id)==false)
+ {
+ return NULL;
+ }
+
+ $code=$database->get_code_of_node($node_id);
+ if($code==NULL)
+ {
+ return NULL;
+ }
+ if($use_https)
+ {
+ return "https://".$domain_name."/share?file=".$code;
+ }else
+ {
+ return "http://".$domain_name."/share?file=".$code;
+ }
+ }
?>
F diff --git a/php/readfile.php b/php/readfile.php
--- a/php/readfile.php
+++ b/php/readfile.php
}
header("Content-type: $file_node[mimetype]");
-
readfile("$storage_root/$file_node[code]");
F diff --git a/php/share.php b/php/share.php
new file mode 100644
--- /dev/null
+++ b/php/share.php
+ <?php
+ require_once "configuration.php";
+ require_once "database.php";
+ require_once "user.php";
+ session_start();
+
+ $user=$_SESSION['user_object'];
+
+
+ if($_SERVER["REQUEST_METHOD"] == "POST")
+ {
+ $path=$_POST["folder"];
+ /*this could be a directory as well*/
+ $filename=$_POST["filename"];
+ $users=$_POST["users"];
+ $password=$_POST["password"];
+ $premissions=$_POST["premissions"];
+
+ if($premissions==1)
+ {
+ $can_read=true;
+ $can_write=false;
+ }else if($premissions==3)
+ {
+ $can_read=true;
+ $can_write=true;
+ }
+ else
+ {
+ http_response_code(409);
+ error_log("someone gave wrong premmissions =".$premissions."! This could be an attack");
+ exit(1);
+ }
+
+ $share_link=create_share_link($path,$filename,$password,$user,$can_read,$can_write);
+
+ if($share_link==NULL)
+ {
+ http_response_code(409);
+ }
+ echo $share_link;
+ http_response_code(200);
+ exit(0);
+ }else if($_SERVER["REQUEST_METHOD"]== "GET")
+ {
+ $code=$_GET["code"];
+ $file_id=$database->get_node_with_code($code);
+ if($file_id==NULL)
+ {
+ http_response_code(409);
+ exit(0);
+ }
+ $premissions=$database->get_premissions($file_id,$user->user_id);
+ if($premissions["can_view"]==true)
+ {
+ $node=$database->get_node($file_id);
+ if($node->is_directory)
+ {
+ /*spooky stuff here*/
+ http_response_code(409);
+ exit(1);
+ }else
+ {
+ header("Content-type: $node[type]");
+ readfile("$storage_root/$node[code]");
+ }
+ }
+
+
+
+ }else
+ {
+ http_response_code(409);
+ exit(0);
+ }
+ ?>
F diff --git a/sql/fileshare.sql b/sql/fileshare.sql
--- a/sql/fileshare.sql
+++ b/sql/fileshare.sql
foreign key (node_id) references nodes(node_id) on delete cascade
);
+ /*we store passwords for the shared links here, it doesn't really have anything to do with the filesystem*/
+ create table shared_nodes (
+ node_id int not null,
+ passcode varchar(100) default "",
+ foreign key (node_id) references nodes(node_id) on delete cascade
+ );
+
create table trash (
node_id int not null
);